|
Post by Packobilly on Nov 16, 2019 20:10:07 GMT
Great. Im working on iMac, but I will try. Im hungry of knowledge im this area. Its an adventure. Thanks indeed, and surely I will be back with new doubts!!
|
|
|
Post by AndyJF on Dec 8, 2019 13:37:52 GMT
Hi Alessandro, I'm having trouble assembling the above code in pasmo or any other assembler I've tried. The assembler I got from here - retrospec.sgn.net/game-links.php?link=z80asm - throws up 'error on line 1' . Pasmo isn't giving me an error message but I suspect it's not working because when I call the routine from within AGD it doesn't do anything. Any idea what I might be doing wrong? Thanks
|
|
|
Post by alessandro on Dec 8, 2019 14:36:57 GMT
Hi Andy, that code must not be called from within AGD, it won't work. It also lacks the "LEFT", "RIGHT" etc. strings to display while each key is pressed. It is meant as an example that must be inserted within a larger "housekeeping" program anyway. This program recalls the AGD-authored game/levels, lets the user choose the controls and/or starting level etc.
Here is another example, taken (with some small modifications) from Lost In My Spectrum. The game has four controls: left, right, jump and pause. Each time a key must be redefined, a print routine is called and the corresponding string is displayed. Please not that keys are not modified on the fly; they are memorized in a specific area, TASTI, to retrieve each time the AGD-authored game (or level) is recalled from memory, and copied at location 35339. This can be redundant if your game has just one level, but in case of multi-level games, each time a level is loaded in memory, controls will be reset to default. So you have to overwrite the key values present in memory when you recall the level with those stored in the TASTI memory area.
BUFFER is a temporary space used for some calculations within the game, e.g. key redefinition, score matching for the high scores table etc.
STAMPA is a print routine based on the RST 16 routine already present in the Spectrum's ROM.
STRINGHE holds the text used in the housekeeping program. It can be customized for different languages, here the English version is presented. The codes before the text set the INK, PAPER and BRIGHT values and the printing position.
The PAUSA subroutine at the beginning is used to avoid that the key pressed in the program's main menu to choose the key redefinition option would also be interpreted as the key to assign to the first control to redefine. 1/5 of a second is enough as a delay to avoid that.
KEYS EQU 35339 ; key location for the game
[...]
RIDEF:
LD B, 10 CALL PAUSA
LD HL, KEYS LD B,6 L_30449: LD (HL),255 INC HL DJNZ L_30449 LD DE,SINISTRA CALL STAMPA LD HL, BUFFER CALL L_30585 LD (KEYS+1),A
LD DE,DESTRA CALL STAMPA
LD HL, BUFFER+1 CALL L_30585 LD (KEYS),A
LD DE,SALTO CALL STAMPA LD HL, BUFFER+2 CALL L_30585 LD (KEYS+4),A
LD DE,HOLD CALL STAMPA
LD HL, BUFFER+3 CALL L_30585 LD (KEYS+5),A
CALL SUONO_RIDEF LD DE,FINE_RIDEF CALL STAMPA LD HL,KEYS ; start: key location LD DE,TASTI ; end: storage area for keys LD BC,6 ; 6 necessary bytes LDIR ; transfer JP ATT_0 ; go back to the initial position in the program's menu L_30585: CALL 654 LD A,E INC A JR Z,L_30585 LD B,05 LD HL,KEYS LD A,E L_30601: CP (HL) JR Z, L_30585 INC HL DJNZ L_30601 RET
STAMPA:
PUSH DE ; keep message address LD A,2 ; upper part
STAMPA_BIS:
CALL 5633 ; open channel POP DE ; retrieve message address... CALL STAMPA_MESS ; ...and print it RET
STAMPA_MESS:
LD A,(DE) ; select character to print INC DE ; point to next character CP 255 ; 255 = text end RET Z ; in this case, return RST 16 ; print JR STAMPA_MESS ; continue until the end RET
PAUSA: ; B holds the pause value in 1/50 of a sec.
HALT
DJNZ PAUSA
RET
BUFFER: DEFS 8 TASTI: DEFS 6
SINISTRA:
DEFB 16, 4, 17, 0, 18, 0, 19, 1 DEFB 22, 21, 12 DEFM "LEFT?"
DEFB 255 ; Text end
DESTRA: DEFB 16, 4, 17, 0, 19, 1 DEFB 22, 21, 12 DEFM "RIGHT?" DEFB 255 ; Text end SALTO:
DEFB 16, 4, 17, 0, 19, 1 DEFB 22, 21, 12 DEFM "JUMP? " DEFB 255 ; Text end
HOLD:
DEFB 16, 4, 17, 0, 19, 1 DEFB 22, 21, 12 DEFM "HOLD" DEFB 255 ; Text end FINE_RIDEF:
DEFB 16, 4, 17, 0, 19, 1 DEFB 22, 21, 12 DEFM " "
DEFB 255 ; Text end
|
|
|
Post by AndyJF on Dec 8, 2019 15:29:55 GMT
Thanks for that Alessandro. I do have a background in programming but I know virtually nothing about assembly language. It's something I would like to learn though.
|
|
|
Post by alessandro on Dec 8, 2019 23:17:42 GMT
Don't worry Andy, I do not know of it much more than that myself, so if I managed to do that, I am sure you can as well
|
|
|
Post by AndyJF on Dec 16, 2019 11:07:18 GMT
Hi, another question about redefining keys - I'm assuming you poke the addresses with the key code? The odd thing is I can only get it to work with the space key (32) If I try to poke the value for another key, say lower case a (97) it doesn't work.
|
|
|
Post by alessandro on Dec 16, 2019 16:45:29 GMT
Andy, you must not assume the key value as the ASCII code, as it is the case with the BASIC INKEY$ function. From Jonathan's How To Write Spectrum Games: Notice that in the cycle at L_30585, that routine is called at the beginning, and the pressed key value is then stored in the A register. The cycle goes back to the start if no key is pressed (if A = 255 and INC A, the A register will revert back to 0, thus complying with the JR Z instruction in the next line). The routine reads the key value and stores it in the memory location corresponding to the AGD memory location for each key, from 35339 on, then goes back to the main program. So you must not worry to POKE the key value yourself; the ROM routine at address 654 will do it for you.
|
|
|
Post by AndyJF on Dec 16, 2019 17:08:51 GMT
Thanks, for the reply, it's gone a little over my head! How do I apply this knowledge to writing a define keys routine in BASIC?
|
|
|
Post by alessandro on Dec 17, 2019 16:34:11 GMT
Hi Andy, there is a way you can redefine keys in BASIC, with some limitations; you cannot, for instance, assign a value to Caps Shift or Symbol Shift, and you can assign more than one value to the same keys.
It is a method used by Mulder in Binary, that I employed in my very first titles, before updating to that Assembly routine I showed you earlier. Here it is (please note that POKEs refer to key locations in AGD v3.2):
2500 REM ridefinizione tasti
2510 INK 7: POKE 23658,8: POKE 32009,1: GO SUB 9000
2520 PRINT AT 3,3; INK 1; "LEFT : ";
2530 BEEP .05,30: PAUSE 10: PAUSE 0: LET K$=INKEY$: BEEP .05,20: GO SUB 3000
2540 POKE 34708,k
2550 PRINT AT 5,3; INK 2; "RIGHT : ";
2560 BEEP .05,30: PAUSE 10: PAUSE 0: LET K$=INKEY$: BEEP .05,20: GO SUB 3000
2570 POKE 34707,k
2580 PRINT AT 7,3; INK 3; "UP : ";
2590 BEEP .05,30: PAUSE 10: PAUSE 0: LET K$=INKEY$: BEEP .05,20: GO SUB 3000
2600 POKE 34710, k
2610 PRINT AT 9,3; INK 4; "DOWN : ";
2620 BEEP .05,30: PAUSE 10: PAUSE 0: LET K$=INKEY$: BEEP .05,20: GO SUB 3000
2630 POKE 34709,k
2640 PRINT AT 11,3; INK 5; "FIRE : ";
2650 BEEP .05,30: PAUSE 10: PAUSE 0: LET K$=INKEY$: BEEP .05,20: GO SUB 3000
2660 POKE 34711,k
2670 PRINT AT 13,3; INK 6; "COLLECT : ";
2680 BEEP .05,30: PAUSE 10: PAUSE 0: LET K$=INKEY$: BEEP .05,20: GO SUB 3000
2690 POKE 34712,k
2700 PRINT AT 15,3; INK 7; "INVENTORY: ";
2710 BEEP .05,30: PAUSE 10: PAUSE 0: LET K$=INKEY$: BEEP .05,20: GO SUB 3000
2720 POKE 34713,k
2730 LET scelta = 1: PAUSE 60: GO TO 90
3000 REM dati tastiera
3010 FOR N=1 TO 40
3020 IF K$=X$(N,1) THEN LET K=N-1
3030 NEXT N
3040 IF K$=CHR$ 13 THEN LET K=33
3050 IF K$=" " THEN LET K=32
3060 PRINT X$(K+1)
3070 RETURN
3080 DATA "B","H","Y","6","5","T","G","V","N","J","U","7","4","R","F","C","M","K","I","8","3","E","D","X","sym","L","O","9","2","W","S","Z","sp","e","P","0","1","Q","A","cp" With a few changes (this is a subroutine, hence the RETURN at line 3070) you can adapt it to your purposes.
|
|
|
Post by AndyJF on Dec 17, 2019 18:32:49 GMT
Thanks Alessandro, that gives me something to work with. I am going to look into writing in assembly but at the moment I'm just refamiliarising myself with spectrum BASIC. I used to do a lot of BASIC programming back in the 80s so it's been fun.
|
|
|
Post by alessandro on Dec 18, 2019 7:49:21 GMT
You are welcome Andy I just realized the BASIC code above is unusable without these lines, data stored in line 3080 must be initialized first - sorry but I didn't include them before: 70 DIM X$(40,3) 80 RESTORE 3080: FOR N=1 TO 40: READ X$(N): NEXT N
|
|
|
Post by alessandro on May 8, 2021 16:21:42 GMT
Hi everyone. Due to a request about a key redefinition routine for all of the 7 keys present in AGD, I am making here public the latest revision of the routine I presented earlier. Please note that FADER, PAUSA, ATTESA and STAMPA refer to other routines present in the code as well - a fading effect, a pause cycle based upon the value of the B register, a "wait for a key press" routine, and a printing routine employing the usual ROM call at RST 16. KEYS refers to a 7 byte long space where to store the key values in order to reuse them in the actual game through a simple LDIR operation starting from the address of the first key, which in AGD 4.7 is 35339. Feel free to modify as needed. Hope that helps
AFFERM EQU 83 ; S(ì) = 83, Y(es) = 89 , J(a) = 74, N(o/on/ein) = 78, O(ui) = 79
[...]
LD A,8 LD (23658),A ; forza Caps Lock
RIDEF:
CALL FADER
LD B, 10 CALL PAUSA
LD HL, KEYS LD B,6 L_30449: LD (HL),255 INC HL DJNZ L_30449 LD DE,SINISTRA CALL STAMPA
LD HL, BUFFER CALL L_30585 LD (KEYS+1),A
CALL SPC_KEY LD DE,DESTRA CALL STAMPA
LD HL, BUFFER+1 CALL L_30585 LD (KEYS),A
CALL SPC_KEY LD DE,ALTO CALL STAMPA LD HL, BUFFER+2 CALL L_30585 LD (KEYS+3),A
CALL SPC_KEY
LD DE,BASSO CALL STAMPA LD HL, BUFFER+3 CALL L_30585 LD (KEYS+2),A
CALL SPC_KEY LD DE,FUOCO CALL STAMPA LD HL, BUFFER+4 CALL L_30585 LD (KEYS+4),A
CALL SPC_KEY
LD DE,INVE CALL STAMPA
LD HL, BUFFER+5 CALL L_30585 LD (KEYS+5),A
CALL SPC_KEY LD DE,INVE CALL STAMPA
LD HL, BUFFER+6 CALL L_30585 LD (KEYS+6),A
CALL SPC_KEY
LD HL,KEYS ; partenza: locazione dei tasti LD DE,TASTI ; arrivo: area stoccaggio tasti LD BC,7 ; i 6 byte necessari LDIR ; trasferimento
LD DE, FINE_RIDEF ; chiede se i tasti vanno bene CALL STAMPA CONFERMA:
CALL ATTESA LD A,(LASTK)
; Codici lettere: S = 83, Y = 89 , J = 74, N = 78, O = 79
CP AFFERM ; sì JP Z, MENU_START ; torna alla selezione iniziale
CP 78 ; no JP Z, RIDEF ; torna alla ridefinizione
JR CONFERMA ; in caso di pressione di un altro tasto, torna indietro
L_30585: CALL 654 LD A,E INC A JR Z,L_30585 LD B,05 LD HL,KEYS LD A,E L_30601: CP (HL) JR Z, L_30585 INC HL DJNZ L_30601 RET
SPC_KEY: CALL 798 ; decodifica tasto
CP 32 ; è SPAZIO? JR NZ, ENT_KEY LD DE, SPC LD BC, 3 CALL 8252 JR SUONO_RIDEF
ENT_KEY: CP 13 ; è ENTER? JR NZ, SYM_KEY LD DE, ENT LD BC, 3 CALL 8252 JR SUONO_RIDEF
SYM_KEY:
CP 24 ; è SYMBOL SHIFT? JR NZ, CAP_KEY LD DE, SYM LD BC, 3 CALL 8252 JR SUONO_RIDEF
CAP_KEY:
CP 39 ; è CAPS SHIFT? JR NZ, PRINT_KEY LD DE, CAP LD BC, 3 CALL 8252 JR SUONO_RIDEF PRINT_KEY:
RST 16
SUONO_RIDEF: LD HL,673 ; RE5# LD DE,052 ; 0,2 sec. CALL 949 ; routine ROM del cicalino LD B, 10 CALL PAUSA RET
SINISTRA:
DEFB 16, 1, 17, 0, 18, 0, 19, 1 DEFB 22, 3, 9 DEFM "LEFT? "
DEFB 255 ; Fine testo
DESTRA: DEFB 16, 2, 17, 0, 19, 1 DEFB 22, 5, 9 DEFM "RIGHT? " DEFB 255 ; Fine testo ALTO: DEFB 16, 3, 17, 0, 19, 1 DEFB 22, 7, 9 DEFM "UP? " DEFB 255 ; Fine testo
BASSO: DEFB 16, 4, 17, 0, 19, 1 DEFB 22, 9, 9 DEFM "DOWN? " DEFB 255 ; Fine testo
FUOCO:
DEFB 16, 5, 17, 0, 19, 1 DEFB 22, 11, 9 DEFM "FIRE? " DEFB 255 ; Fine testo
INVE:
DEFB 16, 6, 17, 0, 19, 1 DEFB 22, 13, 9 DEFM "INVENTORY? " DEFB 255 ; Fine testo
HOLD:
DEFB 16, 7, 17, 0, 19, 1 DEFB 22, 15, 9 DEFM "HOLD? " DEFB 255 ; Fine testo
FINE_RIDEF:
DEFB 16, 7, 17, 0, 18, 1, 19, 1 ; INK 3, PAPER 0, BRIGHT 1 DEFB 22, 18, 9 DEFM " OK? (Y/N)"
DEFB 255 ; Fine testo
SPC:
DEFM "SPC" ENT:
DEFM "ENT"
SYM:
DEFM "SYM"
CAP:
DEFM "CAP"
|
|
|
Post by alessandro on May 8, 2021 18:08:56 GMT
Just for clarification: here are the STAMPA, PAUSA and ATTESA routines - as you can see, they are really simple, even a newbie in Z80 Assembly like yours truly can understand them FADER can be safely omitted and substituted by a CALL 3503 which is the same as CLS. Note: Call STAMPA_SOTTO if you need to print at lines 22 and 23, but remember to treat them as lines 0 and 1 respectively in your AT x,y code, e.g.: DEFB 22, 0, 4 followed by the message and then CALL STAMPA_SOTTO will print the text message at 23,4. Also, always remember to end your text messages with DEFB 255 which is used as the "end of text" character. STAMPA:
PUSH DE ; conserva l'indirizzo del messaggio LD A,2 ; parte superiore
STAMPA_BIS: CALL 5633 ; apri il canale POP DE ; riprendi l'indirizzo del messaggio... CALL STAMPA_MESS ; ...e stampalo RET
STAMPA_MESS: LD A,(DE) ; seleziona il carattere da stampare INC DE ; punta al prossimo carattere CP 255 ; 255 = fine del testo RET Z ; in tal caso, ritorna RST 16 ; stampa JR STAMPA_MESS ; prosegui fino alla fine RET
STAMPA_SOTTO: ; per stampare AT 22,... e AT 23,... (22, 0, ... ; 22, 1, ...) PUSH DE LD A,0 JR STAMPA_BIS
ATTESA:
HALT XOR A ; verifica se un tasto è stato premuto IN A,(254) CPL AND 31 RET NZ JR ATTESA
PAUSA: ; valore della pausa in 1/50 sec. in B
HALT DJNZ PAUSA RET
|
|
|
Post by Packobilly on May 9, 2021 6:55:03 GMT
Thanks so much, Alessandro!
|
|