#define SubFP xor a \ sbc hl, deAnd all numbers handled by the 3D engine are signed 8.8fixed-points (eccept for the angles). Speed stands for the number of units per secound. You can't use 16.8 for the position, but you can easily just send everything within 128 units to the 3D engine, in relative coordinates. Everything further than that will probably be to far to see anyway.
;variables used for saving the location. replace locvars with the memory location they should be x .equ locVars y .equ x+2 z .equ y+2 hdir .equ z+2 vdir .equ hdir+1
;Variables used by the 3D engine. replace EngineVars with the memory location they should be. temp .equ EngineVars temp2 .equ temp+2 temp3 .equ temp2+2
;call this routine before rendering each screen Init3D: ldhl, (x) ld (xfrom), hl pushhl lda, (hdir) adda, 64 call SinA pushhl lda, (vdir) adda, 64 call SinA exde, hl popbc call MulFP popde addhl, de ld (xto), hl ldhl, (y) ld (yfrom), hl pushhl lda, (hdir) call SinA pushhl lda, (vdir) adda, 64 call SinA exde, hl popbc call MulFP popde addhl, de ld (yto), hl ldhl, (z) ld (zfrom), hl pushhl lda, (vdir) call SinA popde addhl, de ld (zto), hl ldhl, 0 ld (xup), hl ld (yup), hl ldhl, $0100 ld (zup), hl call InitView ret
;call this routine to move: Move: ldhl, (x) pushhl lda, (hdir) adda, 64 call SinA pushhl lda, (vdir) adda, 64 call SinA exde, hl popbc call MulFP exde, hl ldbc, speed call MulFP popde addhl, de ld (x), hl ldhl, (y) pushhl lda, (hdir) call SinA pushhl lda, (vdir) adda, 64 call SinA exde, hl popbc call MulFP exde, hl ldbc, speed call MulFP popde addhl, de ld (y), hl ldhl, (z) pushhl lda, (vdir) call SinA exde, hl ldbc, speed call MulFP popde addhl, de ld (z), hl ret
;the routines of the 3D engine.
InitView: ;call once every frame, before C3DTo2D ;IN: The engine's vars ;OUT: vars are initialised ;DESTROYS: all registers and the engine's variables ldhl, (xto) ldde, (xfrom) SubFP ld (xto), hl ldhl, (yto) ldde, (yfrom) SubFP ld (yto), hl ldhl, (zto) ldde, (zfrom) SubFP ld (zto), hl ldde, (xto) ldb, d \ ld c, e call MulFP ld (temp), hl ldde, (yto) ldb, d \ ld c, e call MulFP ldde, (temp) addhl, de ld (temp), hl ldde, (zto) ldb, d \ ld c, e call MulFP ldde, (temp) addhl, de call SqrtFP ld (temp), hl ldhl, (xto) ldde, (temp) call DivFP ld (xto), hl ldhl, (yto) ldde, (temp) call DivFP ld (yto), hl ldhl, (zto) ldde, (temp) call DivFP ld (zto), hl ldde, (xup) ldbc, (xto) call MulFP ld (temp), hl ldde, (yup) ldbc, (yto) call MulFP ldde, (temp) addhl, de ld (temp), hl ldde, (zup) ldbc, (zto) call MulFP ldde, (temp) addhl, de ld (temp), hl ldde, (temp) ldbc, (xto) call MulFP ldd, h \ ld e, l ldhl, (xup) SubFP ld (xup), hl ldde, (temp) ldbc, (yto) call MulFP ldd, h \ ld e, l ldhl, (yup) SubFP ld (yup), hl ldde, (temp) ldbc, (zto) call MulFP ldd, h \ ld e, l ldhl, (zup) SubFP ld (zup), hl ldde, (xup) ldb, d \ ld c, e call MulFP ld (temp), hl ldde, (yup) ldb, d \ ld c, e call MulFP ldde, (temp) addhl, de ld (temp), hl ldde, (zup) ldb, d \ ld c, e call MulFP ldde, (temp) addhl, de call sqrtFP ld (temp), hl ;Multiply (temp) with the tangent of (angle)/2, which is, in this test program, equal to 1, so we don't need to multiply ldhl, (xup) ldde, (temp) call DivFP ld (xup), hl ldhl, (yup) ldde, (temp) call DivFP ld (yup), hl ldhl, (zup) ldde, (temp) call DivFP ld (zup), hl ldde, (yup) ldbc, (zto) call MulFP ld (temp), hl ldde, (zup) ldbc, (yto) call MulFP ldd, h \ ld e, l ldhl, (temp) SubFP ld (xcross), hl ldde, (zup) ldbc, (xto) call MulFP ld (temp), hl ldde, (xup) ldbc, (zto) call MulFP ldd, h \ ld e, l ldhl, (temp) SubFP ld (ycross), hl ldde, (xup) ldbc, (yto) call MulFP ld (temp), hl ldde, (yup) ldbc, (xto) call MulFP ldd, h \ ld e, l ldhl, (temp) SubFP ld (zcross), hl ret
C3DTo2D: ;IN: xpoint, ypoint and zpoint vars ;OUT: screenx and screeny are set to the onscreen coordinates for the point ;Will not work if InitView wasn't called before this routine ;destroys all registers and xpoint, ypoint and zpoint ldhl, (xpoint) ldde, (xfrom) SubFP ld (xpoint), hl ldhl, (ypoint) ldde, (yfrom) SubFP ld (ypoint), hl ldhl, (zpoint) ldde, (zfrom) SubFP ld (zpoint), hl ldde, (xpoint) ldbc, (xto) call MulFP ld (temp), hl ldde, (ypoint) ldbc, (yto) call MulFP ldde, (temp) addhl, de ld (temp), hl ldde, (zpoint) ldbc, (zto) call MulFP ldde, (temp) addhl, de ld (temp), hl ld (screenz), hl ;kijk hier of het punt zichtbaar is bit7, h jp nz, InValid ldde, (xpoint) ldbc, (xcross) call MulFP ld (temp2), hl ldde, (ypoint) ldbc, (ycross) call MulFP ldde, (temp2) addhl, de ld (temp2), hl ldde, (zpoint) ldbc, (zcross) call MulFP ;ld de, (temp2) ;ld bc, (zup) ;call MulFP ldde, (temp2) addhl, de ldde, (temp) call DivFP ld (screenx), hl ldde, (xpoint) ldbc, (xup) call MulFP ld (temp2), hl ldde, (ypoint) ldbc, (yup) call MulFP ldde, (temp2) addhl, de ld (temp2), hl ldde, (zpoint) ldbc, (zup) call MulFP ldde, (temp2) addhl, de ldde, (temp) call DivFP ld (screeny), hl ldhl, $0100 ldde, (screenx) SubFP ldb, h \ ld c, l ldde, 48 call MulFP ld (screenx), hl ldde, (screeny) ldhl, $0100 SubFP ldb, h \ ld c, l ldde, 32 call MulFP ld (screeny), hl lda, 1 ret InValid: lda, 0 ret
;These routines are for the math in the 3D engine.
;;;;;;;;;;;;;;;;;;;;;;;;;; MATH ROUTINES ;;;;;;;;;;;;;;;;;;;;;;;;;;;
SqrtA: LD (Asqr),A SRLA JR DataOver DataOver: LD (Bsqr),A LDB,A LD (Csqr),A iterate: LDA,(Bsqr) ldb, a LDa,(Asqr) LDD,A LDE,B dividedbyEreturnA: RLD RLA SUBE JR nc,$+3 ADDA,E LDE,A LDA,D CPL pushaf;1 LDa,(Bsqr) ldb, a popaf;0 ADDA,B SRLA LD (Bsqr),A LDa,(Bsqr) ldb, a LDA,(Csqr) DECA CPB JR z,done pushaf;1 LD (Csqr),a ldb, a popaf;0 JR iterate done: LDA,(Bsqr) RET
;SubFP: ; ;substracts 2 16-bit fixed-point numbers ; ;IN: hl, de ; ;OUT: hl - de in hl ; ;DESTROYS: a, hl ; or a ;clear carry flag ; sbc hl, de ; ret
Div16By8: ;divides a 16-bit number by an 8-bit number ;IN: hl and d ;OUT: hl = hl/d, remainder = a ;DESTROYS: a, b, c, d, hl xora ldb, 16 _D16b8Loop: addhl, hl rla jrc, _D16b8Overflow cpd jrc, _D16b8Skip _D16b8Overflow: subb incl _D16b8Skip: djnz _D16b8Loop ret
MulFP: ;Multiplies 2 16bit fixed-point numbers ;IN: de, bc ;OUT: de * bc in hl ;DESTROYS: af, bc, de, hl bit7, d jr nz, _MulFP_FirstNeg bit7, b jr nz, _MulFP_AnsNeg jr z, _MulFP_AnsPos _MulFP_FirstNeg: bit7, b jr nz, _MulFP_AnsPos _MulFP_AnsNeg: lda, 1 pushaf;1 jr _MulFP_Cont _MulFP_AnsPos: lda, 0 pushaf;1 _MulFP_Cont: bit7, b jr z, _MulFP_BCPos call NegBC _MulFP_BCPos: bit7, d jr z, _MulFP_DEPos call NegDE _MulFP_DEPos: ldhl,0 lda,16 Mul16Loop: addhl,hl rle rld jp nc,NoMul16 addhl,bc jp nc,NoMul16 incde NoMul16: deca jp nz,Mul16Loop ldl, h ldh, e popaf;0 cp1 call z, NegHL ret
;adding fixed-point numbers: ;load one of the numbers in hl, and the other in an other 16-bit register. ;then, do: add hl, <register>
DivFP: ;IN: hl, de ;OUT: hl = hl / de ;DESTROYS: af, hl, bc, d bit7, d jr nz, _DivFP_FirstNeg bit7, h jr nz, _DivFP_AnsNeg jr z, _DivFP_AnsPos _DivFP_FirstNeg: bit7, h jr nz, _DivFP_AnsPos _DivFP_AnsNeg: lda, 1 pushaf jr _DivFP_Cont _DivFP_AnsPos: lda, 0 pushaf _DivFP_Cont: bit7, h jr z, _DivFP_HLPos call NegHL _DivFP_HLPos: bit7, d jr z, _DivFP_DEPos call NegDE _DivFP_DEPos lda, h ldh, l ldl, 0 pushhl;INPUTS: ahl = dividend de = divisor ;1 popix;OUTPUTS: ahl = quotient de = divisor ;0 ldhl,0 ldb,24 _Div24by16loop: addix,ix rla adchl,hl jrc,_Div24by16setbit ora sbchl,de addhl,de jrc,_Div24by16skip _Div24by16setbit: ora sbchl,de incix _Div24by16skip: djnz _Div24by16loop pushix;1 pophl;0 popaf cp1 call z, NegHL ret
Use it like the comments tell you. To render, AFTER calling Init3D, load the x, y and z coordinates in the xpoint, ypoint and zpoint variables (in signed 8.8 fixed-point format). Then call C3D to2D. If the point was behind the camera, a will be set to 0. If the point is in front of the camera, a will be 1. The screen coordinates will be stored in screenx and screeny, and the distance to the point will be stored in screenz.
For inputting those fixed-point numbers, I created a tool in java. If you want to use it, you can download it here: http://dl.dropbox.com/u/11215358/base%20converter.jar To use it to convert a decimal value into hexadecimal, fill in decimal and hexadecimal in the top field, type in the number , make sure the option 'Signed' is enabled and select '8.8 fixed-point' as format. Then click 'convert'. It will then generate the Hexadecimal code in the field at the bottom. Then just take the last 4 characters or add zeros to the front and you've got your hexadecimal number. For debugging, you can switch decimal and hexadecimal and type in a hex number.
Do you want to be able to rotate your ship, then fly in the direction it's facing instead of moving in only 6 directions? Or did i misunderstand your question? If you want this, you are going to need fixed point numbers or inflation by 256. Then you need a sine routine. When the ship is moving, you add sin(hdir + 90°) to the X coordinate, and sin(hdir) to thy Y coordinate, where hdir stands for the direction in the horizontal plane. If you then add movement along the Z axis, the controls remain simple and they might be good enough. If you however want to be able to fly in the 3 dimensions, then you need 2 direction variables. The math to calculate the coordinates will be slightly more complex too. Now you'll have to add sin(hdir + 90°) * sin(vdir + 90°) to your X coordinate, sin(hdir) * sin(vdir + 90°) to your Y coordinate, and sin(vdir) to your z coordinate. You should also keep in mind that if you want to be able to look in different directions, your 3D projection algorithm needs to support rotation of the camera, so a simple 1, 2 or 3 point perspective algorithm (like what you use when making 3D drawings) won't work anymore. You have to go with a perspective projection algorithm. If you don't already use one, you can find a good one on wikipedia, or I can pm you the code for mine, if you want.
Of course it's made up. Nobody can code something like that into a game.
But this story made it a bit scary when today when I was playing a game on a DS, the game suddenly crashed and showed a black screen and after a secound, some white text appeared on it.
The text didn't say 'come follow me', but that an error has occured, followed by some hexadecimal numbers.
I would be a bit nervous, then take the calc of my brother out of the drawers (that poor calc hasn't even seen daylight for a few months) and use that instaed. It's a calc of the same type.
2475: When you have to decide something, but don't know what you should choose, you let your calc generate a random number instead of tossing a coin (true).
If you don't trust anyone from outside this community, then you can always release it in the private matters section. It's invisible to guests and users with a post number below the limit (of which I think it's 100).
does everything else still works the way it's supposed to? If it does, then you can try resetting or reinstalling DCS, and then use http://ourl.ca/12245/234994 If your OS doesn't work correctely anymore (which means it's corrupted), reinstall the os, then see if it works.