Schrijver
| Question...
| Sonic_aka_T
 msx guru Berichten: 2269 | Geplaatst: 16 Maart 2004, 02:06   | Hey all...
Quick question ;P Anyone here know how to find out when the VDP enters HBLANK? Certainly noy bit 5 of status reg #2 as the tech data book suggests.... I tried polling this bit a number of times, but it is *WAY* off when it comes to indicating when HBLANK occurs. I don't want to use machine specific code since this'll go all wrong when those lame 6/7Mhz users start flicking switches...
Any ideas? Guyver? ro? I remember the muzax series having nice and clean splits.... By any chance remember how you did that? (You know, like them coppers...)
Anyways, thanks...
| | GuyveR800 msx guru Berichten: 3048 | Geplaatst: 16 Maart 2004, 02:31   | That is the only way.
The reason it's "way off" is because the Z80 is slow
In a related note, I saw you wrote to flyguille you had splits working in Z80 mode, where the split would be in line 36 while line 32 was specified in R#19. That's a clear signal that your ISR is too slow, you're probably using the standard MSX ISR which pushes all registers.
The reality is most demos DID use machine-specific code. Many of them (including Unknown Reality) didn't work on my Sanyo MSX2+ or turboR (which share the same MSX-ENGINE).
Some tips:
- Use a quick ISR, one that calls your interrupt code as early as possible, push any registers used by your split routine yourself, usually only AF and maybe HL. Also check S#1 to see if it was indeed a line interrupt, and not some moonsound or other interrupt.
- Use a wait loop like this:
loop:
halt
jp loop
This way you should be able to respond to the ISR within 2 lines. At least it works that way for me.
By making some assumptions (like presetting S#1) you could react to a line interrupt within 1 line on Z80.
As for the HR-check... Use it only when you want a split on the line following your line interrupt. | | Sonic_aka_T
 msx guru Berichten: 2269 | Geplaatst: 16 Maart 2004, 12:52   | I am way off on the line int... It doesn't matter much tho, since I don't really care where the routine occurs on the screen. I've already taken this into account with the placement of the ints (I'll set and int on line 30 if I want one on line 32)
I am using the BIOS ISR but again, it doesn't matter much. I just intercept the int from the BIOS hook, prepare all the data I need for the line int (which is the part that takes about 3 lines on Z80) and THEN start polling HBLANK.
Anyways, I'm still way off tho... I'll try something else I had in mind; see if that works... If not I guess it'll come down to a bunch of NOPs anyway...
Stupid MSX... I guess I've gotten so used to GBA by now that I forgot on MSX you actually needed to know how to program...
Ah well, back to the drawing board I guess... | | GuyveR800 msx guru Berichten: 3048 | Geplaatst: 16 Maart 2004, 14:28   | Quote:
| I am using the BIOS ISR but again, it doesn't matter much. I just intercept the int from the BIOS hook, prepare all the data I need for the line int (which is the part that takes about 3 lines on Z80) and THEN start polling HBLANK.
|
PUSH AF
EX AF,AF'
PUSH AF
PUSH BC
PUSH DE
PUSH HL
EXX
PUSH BC
PUSH DE
PUSH HL
PUSH IX
PUSH IY
doesn't matter much?! That's what the BIOS ISR does before it calls any hook.
That alone will cost about a full screen line to process! | | Sonic_aka_T
 msx guru Berichten: 2269 | Geplaatst: 16 Maart 2004, 15:03   | Quote:
| doesn't matter much?! That's what the BIOS ISR does before it calls any hook.
That alone will cost about a full screen line to process!
|
I know, but it doesn't make shit worth of difference. This is independant from the timing problems I am having. All this occurs *before* I poll HBLANK (Why isn't it called this on MSX?). All the ISR overhead means is that I have to set the line-int a little before the actual line I wish to modify occurs. So if I want the split to occur at line 50 I just set the line-int to line 45 if it's a 3.58MHz Z80 cpu. This is not the problem. The problem is that even after I've redone my palette routine to:
WAIT_L: IN A,(C)
AND %00100000
JR Z,WAITLP
INC C
OUT (C),E
OUT (C),D
DEC C
with the palette entry set to the desired color and with $99 in C, it still takes the darn thing to around pixel 80 of the line! How the hell is this possible? Does this mean that 7+7+6+12+12 = 44 T-States is equal to the whole HBLANK period + 80 pixels of the next line!?!? That can't be right; 12usec = half a line!?!?!
Even on R800 it takes like 30 pixels plus the HBLANK period! That can't be right!?! Right?
Anyways... Maybe you've got an aternative approach? | | GuyveR800 msx guru Berichten: 3048 | Geplaatst: 16 Maart 2004, 15:29   | Quote:
|
WAIT_L: IN A,(C)
AND %00100000
JR Z,WAITLP
INC C
OUT (C),E
OUT (C),D
DEC C
|
Replace IN A,(C) with IN A,(99h). <- shortens reaction time by 2 cycles.
Replace the AND %00100000 with a AND B (ofcourse load B with 20h before the loop). <- shortens reaction time by 3 cycles.
Replace the JR with a JP. <- shortens reaction time by 2 cycles.
Use LD A,E + OUT (9Ah),A in stead of INC C + OUT (C),E. <- saves 2 cycles.
You can now either keep the OUT (C),D or use LD A,D + OUT (9Ah),A. Using the latter is safer on MSX's with slow circuitry (like some Sony's), but the first may be faster.
The above changes will shave off 7 cycles from your HR check. Basically this increases the resolution in which you poll the HR bit.
The other 2 saved cycles thankfully compensate a bit for the fact JP is slower than JR when the jump is not taken.
Quote:
| Even on R800 it takes like 30 pixels plus the HBLANK period! That can't be right!?! Right?
|
In R800 mode the S1990 slows down the R800 on every VDP access. These wait states can add up to over a 100 cycles. In fact, your OUT (C),E + OUT (C),D combo will cause a wait in between. Using LD A,D + OUT (9Ah),D for the latter will probably make ZERO difference on R800.
Also keep in mind the HBLANK period does not include the BORDER period. | | Arjan msx addict Berichten: 473 | Geplaatst: 16 Maart 2004, 15:43   | Check this out for some detailed info about screen split programming. | | Sonic_aka_T
 msx guru Berichten: 2269 | Geplaatst: 16 Maart 2004, 16:02   | Heh, I actually tried to do some thinking myself (my brain still hurts!) and it's phunny we came up with pretty much the same shit... The coolest part it that it now works by the way
I knew about the OUT (C)'s but since I'm making this for fly's BIOS I can't take the luxury of assuming the VDP is where it should be. I've heard there's somekind of lame MSX1 to MSX2 extension in south america that has the VDP at who knows what port. Well, and it's basically not very neat for a BIOS to do that kind of shit...
As far as the JP vs JR. I'm looking for speed in case the result is negative. JR takes 7 states on a negative, JP takes 10 states. So JR in this scenario actually saves me 3 states.
Then, I also thought about moving the OUT (C),E to a point before the poll, that was the first thing I did. This freed up E and it also ocurred to me that AND r was faster than AND n. This was the second thing I did -having free up E-.
Then I had to do something *HORRIBLE*. After all the effort I had put in not making self-modifying code I *HAD TO*. That kinda sucks, but I had no way out. So the IN A,(C) was replaced by a IN A,(n) which allows me to take the INC C out. The result is:
LD A,C
LD (WAITLP+1),A
INC C
OUT (C),E
LD E,%00100000
WAIT_L: IN A,($99)
AND E
JR Z,WAIT_L
OUT (C),D
DEC C
DJNZ BAR_LP
This just about seems to work with not a microsec to spare... Me happy... Thanks for your input by the way.... | | flyguille msx master Berichten: 1223 | Geplaatst: 16 Maart 2004, 16:14   | Very interesting information GuyveR800....
sure Aka are making the code that one i need.
| | Arjan msx addict Berichten: 473 | Geplaatst: 16 Maart 2004, 16:18   | ok that's looking cool  I'd still use JP instead of JR though, just like GuyveR800's suggesting since it gives higher accuracy and depending on how often the loop is run through before entering HBLANK it might be faster too. Be sure to test the code in openMSX and run a cputrace to see how often that code will be executed. | | ro msx guru Berichten: 2346 | Geplaatst: 16 Maart 2004, 17:27   | should've sticked to basic dude... uhuhuh
Nah, still don't see the point of all this to be included in some kernel. But hell, for sonic_boy (aka tobiplas da turk) it's a great new learning experience after all.
well, can't add any usefull input here so I might as well shut the *beep* up.
---------------------------------
well, here are the promised SETLNI routines I used:
just dig and see whaz up. It uses a table where LNI_Y and LNY_adr are stored in...
;+----- LNI sys routines -----+
;Install vector_LNI.
;In: HL, LNI Vector Table pointer
INILNI: LD (LNIVEC),HL
LD (LNIVEC+2),HL
CALL NXTLNI
RET
;Set LNI Vector Table
;In: HL, LVT pointer
SETLVT: LD (LNIVEC),HL ;set Org
RET
;Clear vector_LNI
CLRLNI: CALL DISLNI
LD HL,SYSLVT
LD (LNIVEC),HL
LD (LNIVEC+2),HL
RET
;Set next (possible) LNI
;If Ypos=0 then DISLNI
NXTLNI:
LD HL,(LNIVEC+2) ;Sys #
LD E,(HL) ;Adr Low
INC HL
LD D,(HL) ;Adr High
INC HL
LD A,E
AND D
CP #FF
CALL Z,NNLI_N
EX DE,HL ;Set adr on ISR
CALL SETLNI
EX DE,HL
LD A,(VDPBF2+23) ;Set vertical position (Y)
LD E,(HL)
INC HL
ADD E
OUT (#99),A
LD A,#80+19
OUT (#99),A
LD A,E ;Y=0?
AND A ;
JR Z,NLNI.0 ;Yes, then LNI not enable
LD (LNIVEC+2),HL
LD A,(VDPBF1+0) ;LNI Enable
SET 4,A
LD (VDPBF1+0),A
OUT (#99),A
LD A,#80+0
OUT (#99),A
NLNI.0: LD A,0 ;s#0
OUT (#99),A
LD A,#80+15
OUT (#99),A
RET
;Last LNI vector done, set first again.
NNLI_N: LD HL,(LNIVEC) ;Org
LD E,(HL)
INC HL
LD D,(HL)
INC HL
LD A,1 ;s#1
OUT (#99),A
LD A,#80+15
OUT (#99),A
LD A,0
IN A,(#99) ;clr source from int
RET
LNIVEC: DW SYSLVT ;Original Pointer
DW SYSLVT ;System Pointer
SYSLVT: DW #FFFF
DB 0
;Original Pointer
DW SYSLVT ;System Pointer
SYSLVT: DW #FFFF
DB 0
| | ro msx guru Berichten: 2346 | Geplaatst: 16 Maart 2004, 17:29   | and here are the ints I use in MUZAX 3 (the above LNI routs too by the by)
well, this isn't a complete copy.. but a exerpt from the source.. hope you might learn something (go ahead guyv and diss the sources..)
As you might notice I enable Ints again while in another interrupt (using EI) this is done only when I do some pre-calc for example and let other INT interrupt (get it) Also I carefully chose the position to put the hughe overhead of the MBM replayer (and, again, you might EI before doing the routine to get other LNIs on time!)
don't mind to nest interrupts...
I too use the ou(c),d/e sometimes...
;+----- Line Int 0 -----+
LNI_00:
LD A,(VDPBF1+0) ;DisLNI
RES 4,A
OUT (#99),A
LD A,0 OR #80
OUT (#99),A
LD A,2 ; s#2
OUT (#99),A
LD A,#80+15
OUT (#99),A
LNI0.0: IN A,(#99) ;HRT
AND #20
JP Z,LNI0.0
PUSH HL
PUSH DE
PUSH BC
;> Show cycle colours
LD A,(CYCSTA)
AND A
JP Z,LNI0.6
LD HL,CYCBUF
LD BC,CYCLEN/2+4*256+#9A
;Low Colour
LNI0.1: LD A,CYCCOL
OUT (#99),A
LD A,#80+16
OUT (#99),A
LD E,(HL) ;Get RB
LD (HL),BCKRGB AND #77 ;Clear
INC HL
LD D,(HL) ;Get 0G
LD (HL),BCKRGB/256 AND #07 ;Clear
INC HL
LNI0.2: IN A,(#99) ;HRT
AND #20
JP Z,LNI0.2
OUT (C),E ;RGB to VDP
OUT (C),D
;High colour
LD E,(HL) ;Get RB
LD (HL),BCKRGB AND #77 ;Clear
INC HL
LD D,(HL) ;Get 0G
LD (HL),BCKRGB/256 AND #07 ;Clear
INC HL
LNI0.3: IN A,(#99) ;HRT
AND #20
JP Z,LNI0.3
OUT (C),E ;RGB to VDP
OUT (C),D
DJNZ LNI0.1 ;Repeat
CALL NXTLNI ;
EI ;Next LNI possible!
;Calc. and Set colour-cycle data in buffer
LD HL,(CYCBAR) ;Source
LD A,(HL) ;total bars
INC HL
LD B,A
AND A
JP Z,LNI0.6 ;No Bars...
LD A,(CYCBF#)
LNI0.5: PUSH BC
LD BC,(CYCGAP)
ADD A,C
PUSH AF
PUSH HL
CALL GETSIN
ADD A,A  word)
LD B,0
LD C,A
LD HL,CYCBUF ;Dest
ADD HL,BC
EX DE,HL
POP HL
LD BC,2*5
LDIR
POP AF
POP BC
DJNZ LNI0.5
LD A,(CYCBF#) ;Inc Cycle Speed
LD BC,(CYCSPD)
ADD A,C
LD (CYCBF#),A
JP LNI0.7
LNI0.6:
CALL NXTLNI
LNI0.7:
POP BC
POP DE
POP HL
POP AF ;from ISR
EI
RET
;+----- Line Int #1 Page swap etc.-----+
LNI_01: LD A,(VDPBF1+0) ;DisLNI
RES 4,A
OUT (#99),A
LD A,0 OR #80
OUT (#99),A
LD A,2 ; s#2
OUT (#99),A
LD A,#80+15
OUT (#99),A
LD A,(VDPBF1+1) ;Scr Dis
RES 6,A
OUT (#99),A
LD A,1 OR #80
OUT (#99),A
;LNI1.0: IN A,(&H99) ;HRT
; AND &H20
; JP Z,LNI1.0
LD A,#1F ;Page 1
OUT (#99),A
LD A,2 OR #80
OUT (#99),A
LD A,(VDPBF2+8) ;Ena Spr
OUT (#99),A
LD A,8 OR #80
OUT (#99),A
LD A,(VDPBF2+23)
LD (STAR_Y),A
OUT (#99),A
LD A,23 OR #80
OUT (#99),A
PUSH HL
PUSH DE
CALL NXTLNI
LD A,(VDPBF1+1) ;Scr Ena
OUT (#99),A
LD A,1 OR #80
OUT (#99),A
POP DE
POP HL
POP AF ;from ISR
EI
RET
;+----- LNI #2. Colour Flip -----+
LNI_02: LD A,2 ;s#2
OUT (#99),A
LD A,#80+15
OUT (#99),A
LNI2.3: IN A,(#99) ;HRT
AND #20
JP Z,LNI2.3
PUSH BC
PUSH HL
LD A,(VDPBF1+0) ;LNI dis
RES 4,A
LD (VDPBF1+0),A
OUT (#99),A
LD A,#80+0
OUT (#99),A
LD HL,CFT_00+6
LD B,16
LNI2.1: LD A,15 ;Color=
OUT (#99),A
LD A,#80+16
OUT (#99),A
LD A,(HL)
INC HL
OUT (#9A),A
LNI2.2: IN A,(#99) ;HRT
AND #20
JP Z,LNI2.2
LD A,(HL)
INC HL
OUT (#9A),A
DJNZ LNI2.1
PUSH DE
PUSH IX
LD BC,(FLP_DY)
LD A,(FLP_SY)
CP C
JP Z,LNI2.0
JP C,LNI2_U
LNI2_D: DEC A
DEC A
LNI2_U: INC A
LD (FLP_SY),A
LNI2.0: CALL NXTLNI
EI
LD IX,CFT_00
CALL CF_CAL
;MBM replayer here 'coz of timing problems
PUSH IY
EX AF,AF
PUSH AF
LD HL,(MBMISR)
POP AF
EX AF,AF
CALL JUMPER
POP IY
POP IX
POP DE
POP HL
POP BC
POP AF ;From ISR
EI
RETI
;+----- LNI #3. Bottem Colour Flip -----+
LNI_03: LD A,2 ; s#2
OUT (#99),A
LD A,#80+15
OUT (#99),A
PUSH DE
PUSH HL
PUSH BC
LNI3.0: IN A,(#99) ;HRT
AND #20
JP Z,LNI3.0
LD A,(VDPBF1+0) ;LNI dis
RES 4,A
LD (VDPBF1+0),A
OUT (#99),A
LD A,#80+0
OUT (#99),A
LD HL,CFT_00+6
LD BC,#089A
;Low Colour
LNI3.1: LD A,CYCCOL
OUT (#99),A
LD A,#80+16
OUT (#99),A
LD E,(HL) ;Get RB
INC HL
LD D,(HL) ;Get 0G
INC HL
LNI3.2: IN A,(#99) ;HRT
AND #20
JP Z,LNI3.2
OUT (C),D ;RGB to VDP
OUT (C),E
;High colour
LD E,(HL) ;Get RB
INC HL
LD D,(HL) ;Get 0G
INC HL
LNI3.3: IN A,(#99) ;HRT
AND #20
JP Z,LNI3.3
OUT (C),D ;RGB to VDP
OUT (C),E
DJNZ LNI3.1 ;Repeat
CALL NXTLNI
EI
PUSH IX
EX AF,AF
PUSH AF
LD HL,(SEEISR)
CALL JUMPER
POP AF
EX AF,AF
POP IX
POP BC
POP HL
POP DE
POP AF ;From ISR
EI
RETI
;Vblank
VBL_00:
LD A,(VDPBF2+8) ;Dis Spr
SET 1,A
OUT (#99),A
LD A,8 OR #80
OUT (#99),A
LD A,(VDPBF1+1) ;Ena scr
OUT (#99),A
LD A,1 OR #80
OUT (#99),A
CALL DOSTAR
LD A,#7F ;page 3 (logo)
OUT (#99),A
LD A,2 OR #80
OUT (#99),A
LD A,1 ;Pal
OUT (#99),A
LD A,#80+16
OUT (#99),A
LD HL,CF_TB0+6+2
LD BC,#1A9A
OTIR
LD A,(VBLCNT)
INC A
CP 2
JP C,VBL0.0
CALL VBLKEY
XOR A
VBL0.0: LD (VBLCNT),A
EI
LD IX,CF_TB0
CALL CF_CAL
RET
| | Sonic_aka_T
 msx guru Berichten: 2269 | Geplaatst: 16 Maart 2004, 17:51   | Quote:
| ok that's looking cool  I'd still use JP instead of JR though, just like GuyveR800's suggesting since it gives higher accuracy and depending on how often the loop is run through before entering HBLANK it might be faster too. Be sure to test the code in openMSX and run a cputrace to see how often that code will be executed.
|
No, in this case I *must* use JR instead of JP. Eventhough JP is two states faster on a positive it will be anywhere from 1 - 3 states slower on a negative (depending on when HR goes high). Although 1 - 3 states doesn't seem like much, it's apparantly just what I need. If I change JR into JP it doesn't work anymore... No joke... | | Sonic_aka_T
 msx guru Berichten: 2269 | Geplaatst: 16 Maart 2004, 17:59   | Hey Ro!
Good to hear from you... Well, turns out what the problem was... It was the OUT (c)'s that take too long. Since on MSX I always used OUT ($99),A there was no problem. And I really didn't give a crap about the 7 people that don't have their VDP at $98.
The problem turned out to be the added states for OUT (C) vs OUT (n) and more importantly, the added INC C. I just never realized it was *that* time critical. And since I was always used to fixing the VDP port the problem had never occured before.
I did learn from this tho, I would have never thought a JR would be faster than a JP.
Ah well...
Thanks all... | | GuyveR800 msx guru Berichten: 3048 | Geplaatst: 16 Maart 2004, 18:48   | As the VDP and the Z80 don't run in perfect sync, I don't think your findings about the JR vs. JP are applicable always.
| |
| |
| |