Short fallout style text game (Merged from multiple topics)

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Short fallout style text game

Post by ParadigmShifter »

You don't need a divide routine to print decimal numbers from -32768 to 32767. I use this which I ripped off from this excellent site. It's even easier if you encode as ASCII or BCD. EDIT: Maybe I ripped it off from another site from reading the comment :) It's fast though.

http://z80-heaven.wikidot.com/math#toc32

Code: Select all

; based on code from here http://map.grauw.nl/sources/external/z80bits.html#5.1
; and the 2's complement without using a spare register was from here
; https://wikiti.brandonw.net/index.php?title=Z80_Routines:Other:DispA#Decimal_Signed_Version
; Input: HL = number to convert, DE = location of ASCII string
; Output: ASCII string at (DE)
signedhltodecimal:
	bit 7, h
	jr z, hltodecimal
	ld a, '-'
	ld (de), a
	; negate hl
	xor a
	sub l
	ld l, a
	ld a, 0     ; Note that XOR A or SUB A would disturb CF
	sbc a, h
	ld h, a
	inc de
hltodecimal:
	ld bc, -10000
	call .num1
	ld bc, -1000
	call .num1
	ld bc, -100
	call .num1
	ld c, -10
	call .num1
	ld c, b
.num1 
	ld a, '0' - 1
.num2	
	inc	a
	add	hl, bc
	jr c, .num2
	sbc	hl, bc
	ld (de), a
	inc	de
	ret
Usage:

Code: Select all

	ld de, char_buff
	call signedhltodecimal
You need a buffer to fill as well (and you need to strip leading zeroes if you care about that)

Code: Select all

char_buff BLOCK 8
If BLOCK does not work in your assembler you have to use

Code: Select all

char_buff
    db 0, 0, 0, 0, 0, 0, 0, 0
EDIT: CALL hltodecimal does an unsigned version as well.

EDIT2: I don't think I've ever used a multiply routine and certainly never a divide one :)

Here's how I skip leading zeros

Code: Select all

	ld de, char_buff
	call signedhltodecimal
.print
	xor a
	ld (de), a; null terminate the string
	ld hl, char_buff
	call skipleadingzeros
.doprintrest
	ld a, (hl)
	or a
	ret z
	call puts

Code: Select all

; HL points to string of digits
skipleadingzeros:
	ld c, 0 ; set to 1 if starts with '-'
	ld a, (hl)
	cp '-'
	jr z, .isnegative
.nextdigit
	cp '0'
	jr nz, .doret
	inc hl
	ld a, (hl)
	or a
	jr nz, .nextdigit
	dec hl
.doret
	dec c
	ret nz
	dec hl
	ld a, '-'
	ld (hl), a
	ret
.isnegative
	inc c
	inc hl
	ld a, (hl)
	jr .nextdigit
"puts" just outputs a 0 (null) terminated string which you should have a version of already
Last edited by ParadigmShifter on Thu Oct 05, 2023 1:01 pm, edited 1 time in total.
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Short fallout style text game

Post by ParadigmShifter »

It's not cheating to research already existing (debugged and tested) routines on tinterwebs btw.

Don't reinvent the wheel unless you have to.

Understanding what code does/how it works is important of course though.

EDIT: The convert to signed uses a clever trick where it effectively calls itself multiple times recursively (for each digit) which is something I have not really done before :)

So what it's doing is going "is it <= 9999"? Then put a 0 in the buffer, subtract 10000, then carry on. Then "is it <= 999"? Then put a 0 in the buffer, subtract 1000 and carry on, etc. It's a bit more complicated than that but if you step through with a debugger (use decimal instead of hex register display) and test a few numbers you should get an idea of how it works. (If it is >= 10000 it repeatedly subtracts 10000 until it isn't and a counter goes from '0' upwards when it does that). So worst case for unsigned is 59999 and I can't be bothered to work out how the signed case works :)

It's cleverer than the usual way they teach you to do it which is build the string in reverse order I think (using mod 10 and divide by 10 operations - slow) and then reverse it or process it backwards when stripping leading zeros.
Wall_Axe
Manic Miner
Posts: 500
Joined: Mon Nov 13, 2017 11:13 pm

Re: Short fallout style text game

Post by Wall_Axe »

I ended up doing that subtraction routine myself, but also used divide to print the correct number of hundreds and tens.
My routine is a lot longer than the one you posted.lol
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Short fallout style text game

Post by ParadigmShifter »

I added a brief explanation of what it does... worth stepping through though to find out.

Signed case just converts to unsigned first after first placing a '-' at start of the buffer. Dunno why I used code which does not trash another register to negate (2's complement) a 16 bit register since BC is not used at that point and the routine is going to trash BC anyway. Maybe it was quicker or I was drunk at the time :)

EDIT: On modern hardware, divide and modulo method is probably faster than looping subtracting stuff but the Z80 is not modern hardware :) Of course, you'd be using a high level language and they have a super optimised version of this anyway and you defo wouldn't be using assembly language to do it!

Best practices from the 80s are certainly not best practice today :)

EDIT2: But at least it is possible on a Z80 to understand everything that is happening unlike these days with pipelines up the wazoo, predictive branching and caches etc. But the chips use a ton of power and have at least umpteen bazillion transistors.

Self modifying code is super bad when you have a cache of course.
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Idea for x-platform language

Post by ParadigmShifter »

Anyway, you mentioned you were wanting to implement keyboard input and such.

For ASM:

You may want to have a look at this thread on the other forum where I posted a basic console framework with input and echoing a keyboard buffer when return is pressed.

https://worldofspectrum.org/forums/disc ... amework/p1

- I probably should have used the ROM to read the keyboard but I didn't ;)
- I went off on one trying to implement functions with parameters then I got Covid and didn't work on it for a month or 2 and now I've forgotten all about it
- there were some gnarly cursor flashing bugs - but if you have a solid cursor or don't have a cursor at all that's fine to start with?

Stuff supported from the off

- keyboard input to a buffer
- some basic editing of line
- scrolling
- output of 8 bit register/memory location as hex digits
- don't think the code size got above 4K at any point

Pic posted in image #1 of that thread, try and assemble and run that first off


Image
Wall_Axe
Manic Miner
Posts: 500
Joined: Mon Nov 13, 2017 11:13 pm

Re: Idea for x-platform language

Post by Wall_Axe »

Yeah I'm sticking with assembly. I don't think such a fictional language would be available for some time..if ever.
C is simpler than this fictional language but harder to implement and more resource hungry.
There would be no 'byte a=5 if a==7 '
It would be more like checking flags in z80 and c64 but in a unified way.

I haven't had much time to code, so nothing has happened in terms of the 3 room game :)

The console thing wouldn't help me as my game is like the menus in a jrpg , just moving an arrow to select options. Everything has to be in an exact place on the screen for that. It's not actually a text adventure where you type anything.
In fallout you have entire conversations by simply choosing from a menu ,not typing.
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Idea for x-platform language

Post by ParadigmShifter »

Ok well implement a menu then with either 1, 2, 3, etc. for option input or cursor up/down/select. EDIT: Up/down/choose option is probably easier than 1, 2, 3, etc. since you only have to handle 3 keys then.

Make the menus generic so you can set the text for each item. Don't worry about how to process the choice yet, just find out what the choice was.

Start with the simplest possible thing and then build on that.
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Idea for x-platform language

Post by ParadigmShifter »

So here's your homework ;)

Have 3 room descriptions (can be "Room 1", "Room 2", "Room 3" if you want - just make sure the descriptions can be arbitrary length).

Start in room1

Display room description

Display menu

Have 3 menus, menu is set per room

Room 1 menu choices

1. Go to room 2
2. Go to room 3

Room 2 menu choices

1. Go to room 1
2. Go to room 3

Room 3 menu choices

1. Go to room 1
2. Go to room 2

Wait for user input

If it is valid, return which item was picked. Otherwise stay in the menu

Bonus points: Move from room to room depending on option picked.
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Idea for x-platform language

Post by ParadigmShifter »

Pop quiz time:

The best way to build up a library of functions is?

a) write all the functions you will ever need before you build anything that works as a game

or

b) build a simple game and write functions as you go, and then learn which ones are either adequate or will need improvement along the way

You decide...
Wall_Axe
Manic Miner
Posts: 500
Joined: Mon Nov 13, 2017 11:13 pm

Re: Idea for x-platform language

Post by Wall_Axe »

I am writing them as I need them.
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Idea for x-platform language

Post by ParadigmShifter »

Okiedoke. Well I think you were working on reading the keyboard so have a look at this and read the comments in the code, should easily be adapted to your needs. (I am using WASD for cursors and it can also handle Z - move down and left and C - move down and right - at the moment).

Code: Select all

; at exit, B contains 1 if we pressed down and -1 if we pressed up
; at exit, C contains 1 if we pressed right and -1 if we pressed left
read_keyboard:
	; Read these ports to scan keyboard
	; bit N (0-based) is clear if the key is being pressed
	; #FE - SHIFT, Z, X, C, & V
	; #FD - A, S, D, F, & G
	; #FB - Q, W, E, R, & T
	; #F7 - 1, 2, 3, 4, & 5
	; #EF - 0, 9, 8, 7, & 6
	; #DF - P, O, I, U, & Y
	; #BF - ENTER, L, K, J, & H
	; #7F - SPACE, FULL-STOP, M, N, & B
	; ld a, port
	; in a, (#FE)
	; to do the read of the port

	ld bc, 0
	ld d, b
	ld e, b

	; are we pressing W?
	ld a, #FB
	in a, (#FE)
	bit 1, a
	jr nz, .notpressingW
	dec b
.notpressingW
	; are we pressing A, S or D?
	ld a, #FD
	in a, (#FE)
	bit 1, a
	jr nz, .notpressingS
	inc b
.notpressingS
	; are we pressing A?
	bit 0, a
	jr nz, .notpressingA
	dec c
.notpressingA
	; are we pressing D?
	bit 2, a
	jr nz, .notpressingD
	inc c
.notpressingD
	; are we pressing I?
	ld a, #DF
	in a, (#FE)
	bit 1, a
	jr nz, .notpressingI
	dec d
.notpressingI
	; are we pressing J, K or L?
	ld a, #BF
	in a, (#FE)
	; are we pressing K?
	bit 2, a
	jr nz, .notpressingK
	inc d
.notpressingK
	; are we pressing J?
	bit 3, a
	jr nz, .notpressingJ
	dec e
.notpressingJ
	; are we pressing L?
	bit 1, a
	IF DIAGONALS_ZC
	jr nz, .notpressingL
	ELSE
	ret nz
	ENDIF
	inc e

	IF DIAGONALS_ZC
.notpressingL
	; are we pressing Z?
	ld a, #FE
	in a, (#FE)
	bit 1, a
	jr nz, .notpressingZ
	ld c, -1
	ld b, 1
.notpressingZ
	; are we pressing C?
	ld a, #FE
	in a, (#FE)
	bit 3, a
	jr nz, .notpressingC
	ld b, 1
	ld c, b
.notpressingC
	ENDIF
.doret
	ret
Wall_Axe
Manic Miner
Posts: 500
Joined: Mon Nov 13, 2017 11:13 pm

Re: Idea for x-platform language

Post by Wall_Axe »

ParadigmShifter wrote: Tue Oct 10, 2023 10:02 am Okiedoke. Well I think you were working on reading the keyboard so have a look at this and read the comments in the code, should easily be adapted to your needs.
thanks, this and the code to get the screen address from x and y are the only code that is not mine.
Im not adverse to using other people's code at all.

Am I right in assuming this is for WASD controls?
how does someone actually see if W is pressed when calling this function?
should i put my own JP instruction after 'notpressingW' and branch off from there?

EDIT=oh i see its the contents of C and B.
So it also seems to check IKJL controls.

Quote reduced by admin
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Idea for x-platform language

Post by ParadigmShifter »

Wall_Axe wrote: Tue Oct 10, 2023 1:04 pm thanks, this and the code to get the screen address from x and y are the only code that is not mine.
Im not adverse to using other people's code at all.

Am I right in assuming this is for WASD controls?
how does someone actually see if W is pressed when calling this function?
should i put my own JP instruction after 'notpressingW' and branch off from there?

EDIT=oh i see its the contents of C and B.
So it also seems to check IKJL controls.
Yeah it's checking IJKL as well and it uses D and E for that, forgot to put that in the comment ;)

I'm using WASD for up/left/down/right and will be using IJKL for spin and shuffle as well.

It's easy to change the keys you look for see the comment about ports and what bits they set.

If DIAGONALS_ZC is 1 it also checks for Z and C
use
DIAGONALS_ZC EQU 0 to turn that off
Wall_Axe
Manic Miner
Posts: 500
Joined: Mon Nov 13, 2017 11:13 pm

Re: Short fallout style text game (Merged from multiple topics)

Post by Wall_Axe »

using assembler allows for better control, in some languages getting one movement per keypress is difficult.
Boriel for example needs a lot of halt instructions to be added

Image
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Short fallout style text game (Merged from multiple topics)

Post by ParadigmShifter »

Yup that's getting there.

You probably do want a halt if you are checking input otherwise you will get multiple keypresses registered per frame. You may want to slow the response time down or have a "key delay until repeat" counter and a "key repeat following a repeat" counter as well.

Some things you will want to have a "wait until the key is released" before allowing it to be pressed again, easiest way to do that is to store what was pressed last frame and compare it to what was pressed this frame.

You were asking about signed vs. unsigned a while ago, you need to know how arithmetic operations affect the flags (specifically the sign flag, test with jr p or jr m, carry flag (jp c, jp nc) (when unsigned arithmetic overflows) and the P/V flag (jp pe, jp po) (when signed arithmetic overflows).

WATCH OUT FOR: 16 bit INC/DEC does not set flags. That can be useful sometimes though (can you work out why?).
Spoiler
It's useful because you can do this

Code: Select all

; do something with A which sets flags e.g.
    OR A
   ; but we want to INC HL regardless
   INC HL ; does not affect flags
   JR Z, .somewhere ; so we INC HL regardless of whether OR A set the Z flag or not, saves doing it for each case (Z set/not set)
Also 16 bit ADD does not set flags either but ADC does! LOL! (That last one has trolled me many times in the past).

And you were asking about types well you have to manage all that by yourself, the assembler knows nothing about what a byte is used for :)
Wall_Axe
Manic Miner
Posts: 500
Joined: Mon Nov 13, 2017 11:13 pm

Re: Short fallout style text game (Merged from multiple topics)

Post by Wall_Axe »

thanks, my game basically has the input style of a JRPG (but the comparison stops there) so im doing the 'react to keypresses' when the key is released.


its just going to be menus like that for the whole game.

It's probably the simplest game to program, just need to copy pointers to strings to other memory addresses...and...thats mostly it really :D
Maybe a bit of primary school mathematics to resolve fights etc.

The two most annoying things about assembly:
-have to think about IF statements backwards. ie making a label called dontmultiply: and having that backwards logic.
-hard to debug

but it has many advantages of course.

Could you please write a few lines about signed vs unsigned because I have absolutely no idea about how its handled.
Like assume I know nothing about it at all (in assembly)
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Short fallout style text game (Merged from multiple topics)

Post by ParadigmShifter »

I glanced at this after a quick google seems decent enough

https://retrocomputing.stackexchange.co ... n-assembly

I also recommend downloading the Rodney Zaks book... won't teach you about spectrum specific stuff but everything else is golden.
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Short fallout style text game (Merged from multiple topics)

Post by ParadigmShifter »

Also remember CALL and RET can be conditional on flags as well that can be very useful e.g. don't do this

Code: Select all

    OR A ; A == 0?
    JR Z, dontcallfunc
    CALL func
dontcallfunc:
do this instead

Code: Select all

    OR A ; A == 0
    CALL NZ, func
likewise for RET

EDIT: whoops got logic wrong way around in 2nd code example ;)
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Short fallout style text game (Merged from multiple topics)

Post by ParadigmShifter »

Another tip is how to remember what C and NC flags do (for unsigned arithmetic)

LD A, value
CP compareto

JR C, islessthancompareto

C stands for "chibi" of course which is Japanese word for tiny/small :) and NC is non-chibi (not smaller).
Wall_Axe
Manic Miner
Posts: 500
Joined: Mon Nov 13, 2017 11:13 pm

Re: Short fallout style text game (Merged from multiple topics)

Post by Wall_Axe »

Ah that's very useful that call and ret can have conditionals.
Now I can think about the IF statements with normal logic :D
Chibi and non chibi are good ways to remember it esp. With that chibia akumas bloke.
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Short fallout style text game (Merged from multiple topics)

Post by ParadigmShifter »

Yup that was where I got the tip from :)
Wall_Axe
Manic Miner
Posts: 500
Joined: Mon Nov 13, 2017 11:13 pm

Re: Short fallout style text game (Merged from multiple topics)

Post by Wall_Axe »

Ah that makes sense.

I'm trying to learn about signed vs unsigned.
So inc and dec (not ant and dec) only seem to work in an unsigned way. That's straight forward.

Whereas 'add'puts a bit in the carry if it goes over 255 .
I still don't know how to handle such things. I had a skim through that book from the late seventies but it was way too detailed:D the info I needed seemed to not be there or was hidden in the explanations of how the chip itself does things.
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Short fallout style text game (Merged from multiple topics)

Post by ParadigmShifter »

Carry means it wraps around from 255 to 0 or vice versa yeah. INC/DEC never sets the carry though (8 bit INC/DEC - but not 16 bit) does set the zero flag and sign flag). So you can do nested loops with 8 bit B and C like so

Code: Select all

    ld c, outerloopcount
.outerloop
    ld b, innerloopcount
.innerloop
    ; do loopy stuff
    djnz .innerloop
    dec c ; this will set Z flag if C becomes zero
    jr nz, .outerloop
Overflow is if the sign bit changes (so like the carry but for bit 7 (most significant bit) instead).

Presumably you know about 2's complement and how negative numbers are stored anyway.
Wall_Axe
Manic Miner
Posts: 500
Joined: Mon Nov 13, 2017 11:13 pm

Re: Short fallout style text game (Merged from multiple topics)

Post by Wall_Axe »

It seems like negative numbers are stored with the eighth but representing the plus or minus sign. Negative numbers have zeroes installed of ones?

The only time it would affect me is:
if I set a number to zero in the assembler code with defb.

Then I 'sub' 15. Is the answer --15 or 240?

What if I wanted some bytes to be signed and others unsigned in regards to 'sub'
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Short fallout style text game (Merged from multiple topics)

Post by ParadigmShifter »

You just have to know what you want when you use it

LD A, 255

is same as

LD A, -1

So if the question is "is 255 equal to -1 or 255"? the answer is "both".

When you do an ADD or SUB you need to know whether it is signed or not when you do it.

EDIT: 2's complement just negates the sign of the most significant bit so if it is 8 bits, bit 7 means "-128" instead of "128".

So in binary signed numbers

0 = 0000 0000
1 = 0000 0001
-1 = 1111 1111 = -128 + 64 +32 + 16 + 8 + 4 + 2 + 1

it's like the milometer on a car, of you subtract 1 from 0 you get 9999
Post Reply