It is currently Sun Oct 22, 2017 8:54 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 22 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Fri Jun 29, 2012 9:02 pm 
Offline

Joined: Tue Jul 14, 2009 11:04 am
Posts: 55
I am having a bit of trouble with writing some Z80 code and while I have written some code before, it's been a while and I'm still quite uncomfortable with Z80 as compared to 6502. Here's my WIP code:

ld hl,C000 21 00 C0
ld a,(hl) 7E
jr nz 20 0A

What I'm trying to do is have the code jump when A doesn't equal 0 ala BNE. Any idea of what I'm doing wrong?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 29, 2012 9:10 pm 
Offline

Joined: Mon Sep 27, 2004 2:57 pm
Posts: 1248
The z80 doesn't set the flags on ld operations. You have to use something like
Code:
or a

to set the flags after an ld.

A little different from 6502, huh? :P


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 30, 2012 11:34 am 
Offline

Joined: Tue Jul 14, 2009 11:04 am
Posts: 55
Heh, figures.

I've pretty much been converting 6502 to Z80 for all my asm mods so far. Sometimes it worked, sometimes not.

Incidentally is there just a doc that just contains all the Z80 instructions for the GB with opcodes and the basic functions? The best I can seem to find is from that unofficial GB programming doc compiled by several people. It's PDF and is a pain in the ass to navigate.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 30, 2012 1:25 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3943
Code:
XOR L   AD
XOR H   AC
XOR E   AB
XOR D   AA
XOR C   A9
XOR B   A8
XOR A   AF
XOR (HL)   AE
SWAP L   35CB
SWAP H   34CB
SWAP E   33CB
SWAP D   32CB
SWAP C   31CB
SWAP B   30CB
SWAP A   37CB
SWAP (HL)   36CB
SUB L   95
SUB H   94
SUB E   93
SUB D   92
SUB C   91
SUB B   90
SUB A   97
SUB (HL)   96
STOP ""   10
SRL L   3DCB
SRL H   3CCB
SRL E   3BCB
SRL D   3ACB
SRL C   39CB
SRL B   38CB
SRL A   3FCB
SRL (HL)   3ECB
SRA L   2DCB
SRA H   2CCB
SRA E   2BCB
SRA D   2ACB
SRA C   29CB
SRA B   28CB
SRA A   2FCB
SRA (HL)   2ECB
SLA L   25CB
SLA H   24CB
SLA E   23CB
SLA D   22CB
SLA C   21CB
SLA B   20CB
SLA A   27CB
SLA (HL)   26CB
SCF ""   37
SBC A,L   9D
SBC A,H   9C
SBC A,E   9B
SBC A,D   9A
SBC A,C   99
SBC A,B   98
SBC A,A   9F
SBC A,(HL)   9E
RST 38H   FF
RST 30H   F7
RST 28H   EF
RST 20H   E7
RST 18H   DF
RST 10H   D7
RST 08H   CF
RST 00H   C7
RRCA ""   0F
RRC L   0DCB
RRC H   0CCB
RRC E   0BCB
RRC D   0ACB
RRC C   09CB
RRC B   08CB
RRC A   0FCB
RRC (HL)   0ECB
RRA ""   1F
RR L   1DCB
RR H   1CCB
RR E   1BCB
RR D   1ACB
RR C   19CB
RR B   18CB
RR A   1FCB
RR (HL)   1ECB
RLCA ""   07
RLC L   05CB
RLC H   04CB
RLC E   03CB
RLC D   02CB
RLC C   01CB
RLC B   00CB
RLC A   07CB
RLC (HL)   06CB
RLA ""   17
RL L   15CB
RL H   14CB
RL E   13CB
RL D   12CB
RL C   11CB
RL B   10CB
RL A   17CB
RL (HL)   16CB
RETI ""   D9
RET Z   C8
RET NZ   C0
RET NC   D0
RET C   D8
RET ""   C9
PUSH HL   E5
PUSH DE   D5
PUSH BC   C5
PUSH AF   F5
POP HL   E1
POP DE   D1
POP BC   C1
POP AF   F1
OR L   B5
OR H   B4
OR E   B3
OR D   B2
OR C   B1
OR B   B0
OR A   B7
OR (HL)   B6
NOP ""   00
LDI A,(HL)   2A
LDI (HL),A   22
LDD A,(HL)   3A
LDD (HL),A   32
LD SP,HL   F9
LD L,L   6D
LD L,H   6C
LD L,E   6B
LD L,D   6A
LD L,C   69
LD L,B   68
LD L,A   6F
LD L,(HL)   6E
LD H,L   65
LD H,H   64
LD H,E   63
LD H,D   62
LD H,C   61
LD H,B   60
LD H,A   67
LD H,(HL)   66
LD E,L   5D
LD E,H   5C
LD E,E   5B
LD E,D   5A
LD E,C   59
LD E,B   58
LD E,A   5F
LD E,(HL)   5E
LD D,L   55
LD D,H   54
LD D,E   53
LD D,D   52
LD D,C   51
LD D,B   50
LD D,A   57
LD D,(HL)   56
LD C,L   4D
LD C,H   4C
LD C,E   4B
LD C,D   4A
LD C,C   49
LD C,B   48
LD C,A   4F
LD C,(HL)   4E
LD B,L   45
LD B,H   44
LD B,E   43
LD B,D   42
LD B,C   41
LD B,B   40
LD B,A   47
LD B,(HL)   46
LD A,L   7D
LD A,H   7C
LD A,E   7B
LD A,D   7A
LD A,C   79
LD A,B   78
LD A,A   7F
LD A,(HL)   7E
LD A,(DE)   1A
LD A,(BC)   0A
LDH A,(C)   F2
LD (HL),L   75
LD (HL),H   74
LD (HL),E   73
LD (HL),D   72
LD (HL),C   71
LD (HL),B   70
LD (HL),A   77
LD (DE),A   12
LD (BC),A   02
LDH (C),A   E2
JP HL   E9
INC SP   33
INC L   2C
INC HL   23
INC H   24
INC E   1C
INC DE   13
INC D   14
INC C   0C
INC BC   03
INC B   04
INC A   3C
INC (HL)   34
HALT ""   76
EI ""   FB
DI ""   F3
DEC SP   3B
DEC L   2D
DEC HL   2B
DEC H   25
DEC E   1D
DEC DE   1B
DEC D   15
DEC C   0D
DEC BC   0B
DEC B   05
DEC A   3D
DEC (HL)   35
DAA ""   27
CPL ""   2F
CP L   BD
CP H   BC
CP E   BB
CP D   BA
CP C   B9
CP B   B8
CP A   BF
CP (HL)   BE
CCF ""   3F
AND L   A5
AND H   A4
AND E   A3
AND D   A2
AND C   A1
AND B   A0
AND A   A7
AND (HL)   A6
ADD HL,SP   39
ADD HL,HL   29
ADD HL,DE   19
ADD HL,BC   09
ADD A,L   85
ADD A,H   84
ADD A,E   83
ADD A,D   82
ADD A,C   81
ADD A,B   80
ADD A,A   87
ADD A,(HL)   86
ADC A,L   8D
ADC A,H   8C
ADC A,E   8B
ADC A,D   8A
ADC A,C   89
ADC A,B   88
ADC A,A   8F
ADC A,(HL)   8E
XOR *   EE
SUB *   D6
SET *,L   C5CB
SET *,H   C4CB
SET *,E   C3CB
SET *,D   C2CB
SET *,C   C1CB
SET *,B   C0CB
SET *,A   C7CB
SET *,(HL)   C6CB
SBC A,*   DE
RES *,L   85CB
RES *,H   84CB
RES *,E   83CB
RES *,D   82CB
RES *,C   81CB
RES *,B   80CB
RES *,A   87CB
RES *,(HL)   86CB
OR *   F6
LD SP,*   31
LD L,*   2E
LD HL,SP+*   F8
LD HL,*   21
LD H,*   26
LD E,*   1E
LD DE,*   11
LD D,*   16
LD C,*   0E
LD BC,*   01
LD B,*   06
LD A,(*)   FA
LDH A,(*)   F0
LD A,*   3E
LD (HL),*   36
LD (*),SP   08
LD (*),A   EA
LDH (*),A   E0
JR Z,*   28
JR NZ,*   20
JR NC,*   30
JR C,*   38
JR *   18
JP Z,*   CA
JP NZ,*   C2
JP NC,*   D2
JP C,*   DA
JP *   C3
CP *   FE
CALL Z,*   CC
CALL NZ,*   C4
CALL NC,*   D4
CALL C,*   DC
CALL *   CD
BIT *,L   45CB
BIT *,H   44CB
BIT *,E   43CB
BIT *,D   42CB
BIT *,C   41CB
BIT *,B   40CB
BIT *,A   47CB
BIT *,(HL)   46CB
AND *   E6
ADD SP,*   E8
ADD A,*   C6
ADC A,*   CE



Copy-pasted (and edited) from a TASM table. Note that asterisks are usually numbers (possibly 8 or 16-bit depending on the instruction), and CB is a byte prefix, not a suffix.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 30, 2012 4:18 pm 
Offline

Joined: Tue Jul 14, 2009 11:04 am
Posts: 55
Code:
ld de,C000 ; dte second pass check
ld a,(de)   
cp a,00
jr nz      
ld hl,C20C    ; original text read routine
ld c,(hl)
inc hl      
ld b,(hl)   
ld a,(bc)   
cp a,50   ; dte check   
jr nc      
ret      
cp a,80      
jr nc      


Alright, so I'm working on converting a dte routine coded in 6502 to z80 and I am at a loss, but at least the first part is working as intended. How exactly does one write something to WRAM? Is the only option to load the RAM offset into hl etc and put A into it?

I also have this bit of code in 6502 that I'm thinking will need to be changed around a bit to get it to work in z80.


Code:
SEC
SBC #$80   
ASL   
TAX
LDA $BD40,X


Two questions, when I want to subtract from A is there an equivalent instruction for SEC or is the carry flag set when I use the SUB command? I'm not sure, but I think that's what the later says in my docs. Lastly what instructions are used to load data from table as in the last LDA? Much appreciate the help.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 30, 2012 4:39 pm 
Offline

Joined: Sat Jan 23, 2010 11:41 pm
Posts: 1161
I think it is better to clear this up: GB does not have Z80. The GB CPU is more like a modified 8080 with some things derived from the Z80 and 6502 even. So answer to a question of the 'how to do this for Z80' kind will be different for GB, as its CPU lacks major number of actual Z80 features.

Writing to the WRAM is not a CPU-related question. Since it is a normal memory, any ways of working with memory will work with it, be it ld (hl),r or ld (nnnn),a etc.

There is a nasty bug in the GB CPU - if you use inc rr or dec rr (bc, de, hl) when its content is in $fe00..$feff range, it corrupts OAM. So use these carefully. It also happens with few other, GB CPU specific opcodes.

Z80 does not have an equivalent for lda nnnn,x. GB CPU does, but only for the scratchpad RAM ($ff00..$ffff). Typical trick for 8080/Z80 is to put data at 256-byte boundary, so LSB part of a register pair will work as an index in a 256-byte block.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 30, 2012 5:21 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3943
Z80 has ld (NNNN),a, or ld (hl),NN. Take your pick.
For where to put things in memory, read the GB memory map. Might need to find some unused memory by running the game in an emulator for a while. Note that old versions of VisualBoyAdvance have a bug: the mirror of RAM is treated as a distinct memory region.

I call it the GBZ80 because the ASM opcodes are written out in a syntax just like the Z80, and most of the opcode byte values match exactly with the Z80. It's close enough for me. But there are still no IX or IY registers, or LDI/CPI/LDIR/CPIR... instructions.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 30, 2012 8:22 pm 
Offline

Joined: Mon Sep 27, 2004 2:57 pm
Posts: 1248
The opcode reference I've been using is this one.
The gameboy hardware reference I've been using is Nocash's, which also has an opcode list.

When you're working with the gameboy, most of your indexed addressing is going to be with HL, DE, and BC. For instance, something like:
Code:
loop:
LDA $----,Y
STA $----
INY
goto loop


will be done like:
Code:
ld hl,----
loop:
ldi a,(hl)  ;increments HL automatically
ld (----),a
goto loop


If both your fetch and store need to be indexed:
Code:
ld hl,----
ld de,----
loop:
ldi a,(hl)
ld (de),a
inc de
goto loop


If I recall correctly, "ldi" doesn't exist on the vanilla z80, so you'd have to put an "inc hl" yourself.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 30, 2012 9:38 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3943
LDI exists on the regular Z80, but it is completely different:
Copy byte from (HL) to (DE), increment hl and de, decrement bc, set overflow flag to whether bc equals zero.
LDIR is the looping version of LDI, and repeats until bc = 0.
These are found on the regular Z80, not the game boy.

Some people use CPI (compare and increment) as an optimization trick on the Z80 when they want to increment HL, decrement BC, and don't care about the compare part.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 30, 2012 9:47 pm 
Offline

Joined: Sat Jan 23, 2010 11:41 pm
Posts: 1161
What is the point of using CPI instead of INC/DEC on Z80? It is slower, 16 t-states vs 2*6, and takes two bytes in any case.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 01, 2012 12:58 am 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3943
CPI sets overflow flag based on value of BC, so you get the comparison for free. Also code size.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 01, 2012 5:30 am 
Offline

Joined: Sat Jan 23, 2010 11:41 pm
Posts: 1161
So your explaination of situation where the trick could be useful was missing important part about the overflow flag. The optimization is only could be achieved when the flag could be actually used. Like, replacing the common code piece (7 bytes, 30 t-states)

Code:
 inc hl
 dec bc
 ld a,b
 or c
 jp nz,loop


with (5 bytes, 26 t-states)

Code:
 cpi
 jp po,loop


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 01, 2012 10:09 am 
Offline

Joined: Tue Jul 14, 2009 11:04 am
Posts: 55
Here's my tested and working dte code. The game executes this code three times before moving onto to the next text byte and that really threw a wrench into my code. I'm this is not the best routine ever, but it does work as intended.

Code:
ld de,C000   11 00 C0   ; dte second pass check   
      ld a,(de)   1A         
      cp a,03      FE 03      ; go to second pass routine if 03
      jr z      28 2F
      cp a,04      FE 04      ; above except slightly modified
      jr z      28 31
      cp a,05      FE 05
      jr z      28 2D
      cp a,06      FE 06
      jr nz      20 03      
      ld a,00      3E 00
      ld de,a      12
      ld hl,C20C   21 0C C2   ; original text read routine
      ld c,(hl)   4E
      inc hl      23
      ld b,(hl)   46
      ld a,(bc)   0A
      cp a,50      FE 50      ; dte check values 50-80
      jr nc      30 01
      ret         C9         ; return if less than 50 or greater than 80
      cp a,80      FE 80
      jr nc      30 FB
      push af      F5
      ld a,(de)   1A         ; increments the dte second pass check byte
      inc a      3C
      ld (de),a   12
      pop af      F1
      sub,50      D6 50      ; subtract 50 from the dte value to be used for the table
      push hl      E5
      ld h1,3B80   21 80 3B   ; loads the base offset for the dte table
      add l      85         ; adds what was previous subtracted to the table
      ld l,a      6F
      ld a,(hl)   7E         ; puts the first dte value in a
      pop hl      E1
      ret         C9
      
      ld hl,C20C   21 0C C2   ; second pass routine only triggered once
      ld a, (hl)   7E         
      dec a      3D         ; decrements the the text offset by 1 to adjust for dte
      ld hl,a      77
      
      ld a,(de)   1A         ; second pass routine, goes here if a < 3
      inc a      3C         ; increments dte flag
      ld (de),a   12
      ld hl,C20C   21 0C C2   ; original text read routine
      ld c,(hl)   4E
      inc hl      23
      ld b,(hl)   46
      ld a,(bc)   0A
      sub,50      D6 50
      push hl      E5
      ld h1,3B80   21 80 3B   ; same dte code
      add l      85
      ld l,a      6F
      inc 1      2C         ; add 1 to the dte table offset for second dte value
      ld a,(hl)   7E
      pop hl      E1
      ret         C9


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 01, 2012 11:54 am 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3943
It looks like you're assembling by hand, are you really doing this? I'd at least set up TASM or something to make a binary, then I can copy-paste assembled code in with a hex editor.

I see some typos in the ASM code, like missing parenthesis on (de) or (hl), or calling hl "h1". Those don't matter if you're assembling by hand, but an assembler would give errors.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 02, 2012 3:40 pm 
Offline

Joined: Tue Jul 14, 2009 11:04 am
Posts: 55
Yeah, I know assembling code by hand isn't the smartest or even the best way to handle writing and developing code. I'm actually waiting for this person called Lin to release his/her assembler for the system. Hopefully, if it's released this summer, I'll be switching over to that.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 22 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group