Jump to content
IGNORED

Bus Stuffing Demos


SpiceWare

Recommended Posts

We can draw the playfield behind the 96 pixels, but only a symmetrical one as the kernel's too busy mid-screen updating the players & colors to also update the playfield registers for the right side.

Perhaps it could be done with a repeating PF instead of mirrored. Also, I'd recommend changing the way the players are staggered.

 

Instead of this:

01 01 01

01 01 01

Do this:
0 0 0 1 1 1

0 0 0 1 1 1

 

That spreads the writes over 8 more pixels and puts a gap in the middle since the first instance of 1 can be set ahead of time. With the repeating PF you can have PF0-PF2 pre filled for the left side and some wiggle room when updating the right side.

Link to comment
Share on other sites

That won't work. Each update to TIA takes 3 cycles, so 6 cycles to update shape and color. In 6 cycles TIA will output 18 pixels. With 8 pixels between each instance of 0 (and 1) there's no way to update shape and color.

 

Symmetrical doesn't mean the playfield is mirrored, it just means the playfield data on the left side is also used on the right. An asymmetrical playfield updates the registers mid-screen so both sides are different. It's possible to have an asymmetrical mirrored playfield - that's how Stay Frosty was done.

Link to comment
Share on other sites

I assumed symmetric implied mirrored for this specific application because a repeating symmetric PF would be impossible to align with only the center 96 pixels. I also assumed the BUS driver supported the read modify write form of bus stuffing which gets you two adjacent write cycles at the end of the 5 cycle instruction. Without that you run out of time.

 

The video you posted looks better than I expected. The tile sized movement actually looks pretty good. Definitely some good RPG potential here.

Link to comment
Share on other sites

I assumed symmetric implied mirrored for this specific application because a repeating symmetric PF would be impossible to align with only the center 96 pixels.

I think Chris' original code used mirrored. It originally turning video on/off during the scanline so I was going to try repeated as the left instance of PF0 and the right instance of PF2(maybe) would be hidden, so I'd only have to squeeze in an update for PF1 on the right:

post-3056-0-13218100-1478184452_thumb.png

 

But another test using a 128 pixel display over an asymmetrical playfield:

post-3056-0-82208100-1478184628_thumb.png

 

caused us to reconsider using the playfield as we didn't care for the transparency that results from using 30 Hz flicker.

 

I also assumed the BUS driver supported the read modify write form of bus stuffing which gets you two adjacent write cycles at the end of the 5 cycle instruction.

We did some tests using Quad Stuffing:

Here is something rather cool - I managed to get bus stuffing working with the ROR instruction, which allows 2 TIA writes in 5 cycles.

 

It is rather more complex than stuffing the STY instruction, which requires a single bus stuffing operation on the data bus. Stuffing the ROR instruction requires 4 bus stuffing operations - 2 for the address bus and 2 for the data bus (so I'm calling it quad stuffing).

 

The following table illustrates what is going on:

           Operation                      Address Bus      Data Bus
Cycle 1    Read ROR                       PC               ROR
Cycle 2    Read $FF                       PC + 1           $FF
Cycle 3    Read value at $FF              $FF              value at $FF
Cycle 4    Write original value to $FF    $FF (stuff)      value at $FF (stuff)
Cycle 5    Write RORd value to $FF        $FF (stuff)      RORd value (stuff)

To make this work, it is necessary to store $FF at location $FF, and set the carry flag, i.e:

lda #$FF
sta $FF
sec
...
ror $FF

 


But the timing required for PAL and NTSC consoles is different - what worked on Chris' PAL system didn't work on mine. We decided to back burner it and concentrate on what was working.

 

The video you posted looks better than I expected. The tile sized movement actually looks pretty good. Definitely some good RPG potential here.

I'm hoping somebody runs with it once we finish the driver and make everything available, as after that I plan to finish Draconian, Frantic and Timmy!

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

NOTE: This was originally posted in this topic.

 

 

There's many ways to implement BUS Stuffing, these answers are specific to the driver we're currently developing for the Harmony/Melody.

 

The 6507 is instructed to STY $FF in an infinite loop.

While it's possible to use STY $FF then stuff the address and the data, timing is difficult for 2+ bus stuffing events per instruction so we only stuff the data. As such, we still have to write the kernel in 6507 code. For the current build of Draconian the upper part of this display (above the green line):

post-3056-0-80505000-1479311319_thumb.png

 

Is created using this kernel:

        ldx #0
...
        stx STUFFMODE       ; 4 13 - turn on bus stuffing

        ldy #$FF            ; 2 15
        sty VDELP0          ; 3 18
        sty VDELBL          ; 3 21
        jmp VBentry         ; 3 24
        
RealNormalKernel:           ; - 20 43 ; 43 is latest to get here
        sty Size            ; 3 24 46 not used, read to keep stream in sync
R46color:                   ; -    46 ; 46 is latest to get here
        sty Color           ; 3 28 49 not used, read to keep stream in sync
R49:                        ; -    49 ; 49 is latest to get here
        sty HMP0            ; 3 31 52 - no HMCLR needed as we are setting them all
        sty HMP1            ; 3 34 55
        sty HMM0            ; 3 37 58
        sty HMM1            ; 3 40 61
        sty HMBL            ; 3 43 64
VBentry:                    ; -    64 
R64:                        ; -    64 ; 64 is latest to get here
        sty GRP0            ; 3 46 67 - VDELP0 on, so this is for next scanline
        sty ENABL           ; 3 49 70 - VDELBL on, so this is for next scanline
        sty NextKernel      ; 3 52 73
R73:                        ; -    73 ; 73 is latest to get here        
        sta WSYNC           ; 3 55 76/0
R76:                        ; - 76/0
        ; at this point GRP0, ENABL and all HMxx values are loaded
        sta HMOVE           ; 3  3
        sty GRP1            ; 3  6 - also updates GRP0 and ENABL due to VDELxx
        sty ENAM0           ; 3  9
        sty ENAM1           ; 3 12
        jmp (NextKernel)    ; 5 17

...

        align 256                     ;   17
NormalKernel:   jmp RealNormalKernel  ; 3 20    
ExitKernel:     jmp RealExitKernel    ; 3 20
Resp0Strobe23:  jmp RealResp0Strobe23 ; 3 20 
Resp0Strobe28:  jmp RealResp0Strobe28 ; 3 20 
Resp0Strobe33:  jmp RealResp0Strobe33 ; 3 20

...

RealResp0Strobe38:          ; -          20
        dec Sleep5          ; 5          25        
RealResp0Strobe33:          ; -       20
        dec Sleep5          ; 5       25 30       
RealResp0Strobe28:          ; -    20 
        dec Sleep5          ; 5    25 30 35
RealResp0Strobe23:          ; - 20   
        sta RESP0           ; 3 23 28 33 38
        sty NUSIZ0          ; 3 26 31 36 41
        sty COLUP0          ; 3 29 34 39 44
        jmp R49             ; 3 32 37 42 47

...

The JumpDatastream (used by sty NextKernel) is currently filled with 0 so every jmp (NextKernel) instruction will go to NormalKernel. The very last value in JumpDatastream is 3, so the final jmp (NextKernel) goes to ExitKernel which is when the green line is drawn. Eventually JumpDatastream will be filled with other values, such as 9 which would cause it to go to Resp0Strobe28 so player0 can be repositioned and reused. There will eventually be Resp1, Resm0, Resm1 and Resbl routines to reposition the other 4 moveable objects.

 

At the same time, C code is running on an ARM core that is updating registers in memory based on how you've programmed your game.

Before the kernel runs your custom C code has to prep a bunch of data and store it in datastreams. For the above, these are the datastreams:

 

 

;----------------------------------------
; Set this to adjust scanlines used for gameplay game area.  
; The +5 is for 5 scanlines to reposition all objects,
; this will be consistantly 5 scanlines vs using PosObject which
; uses an additional scanline for each object that is on the
; right side of the screen
;----------------------------------------
DATASTREAM_SIZE = 160 + 5


JumpDataStream:
        ds DATASTREAM_SIZE-1
ExitJumpDataStream:        
        ds 1
        
        align 2 ; ARM accesses via unsigned short int (WORD)
GRP0_HMP0_DataStream:
        ds DATASTREAM_SIZE*2 
        ds 2    ; Kernel done, turns off player0
 
        align 2 ; ARM accesses via unsigned short int (WORD)
GRP1_HMP1_DataStream:
        ds DATASTREAM_SIZE*2
        ds 2    ; Kernel done, turns off player1
        
ENAM0_HMM0_DataSream:   ; 0.5 increment.  Upper nybble HMM0, bit 1 ENAM0
        ds DATASTREAM_SIZE
        ds 1    ; Kernel done, turns off missile 0
 
ENAM1_HMM1_DataSream:   ; 0.5 increment.  Upper nybble HMM1, bit 1 ENAM1
        ds DATASTREAM_SIZE
        ds 1    ; Kernel done, turns off missile 0
        
ENABL_HMBL_DataStream:  ; 0.5 increment.  Upper nybble HMM1, bit 1 ENAM1
        ds DATASTREAM_SIZE
        ds 1    ; Kernel done, turns off missile 0
        
Color_DataStream:   ; new color of object being repositioned
        ds DATASTREAM_SIZE
 
Size_DataStream:    ; new size of object being repositioned
        ds DATASTREAM_SIZE

The streams are laid out in the 6507 code in Display Data RAM. The 6507 code has a bunch of ECHO statements:

 

       echo "// datastreams"

        echo "#define DATASTREAM_SIZE     ",[DATASTREAM_SIZE]d
        echo "#define JUMP_DATASTREAM     ",[JumpDataStream]d
...


That output this:

 

#define DATASTREAM_SIZE      165
#define JUMP_DATASTREAM      8
...

 

That's copied over to the C code where it uses those defines to make pointers like this:

 

unsigned short int * const gPlayer0Datastream   =(unsigned short int *)(DD_BASE + PLAYER0_DATASTREAM);
unsigned short int * const gPlayer1Datastream   =(unsigned short int *)(DD_BASE + PLAYER1_DATASTREAM);
unsigned char * const gMissile0Datastream       =(unsigned char *)(DD_BASE + MISSILE0_DATASTREAM);
unsigned char * const gMissile1Datastream       =(unsigned char *)(DD_BASE + MISSILE1_DATASTREAM);
unsigned char * const gBallDatastream           =(unsigned char *)(DD_BASE + BALL_DATASTREAM);
unsigned char * const gColorDatastream          =(unsigned char *)(DD_BASE + COLOR_DATASTREAM);
unsigned char * const gSizeDatastream           =(unsigned char *)(DD_BASE + SIZE_DATASTREAM);
unsigned char * const gScoreDatastream          =(unsigned char *)(DD_BASE + SCORE_DATASTREAM);
unsigned char * const gPlayfieldDatastream      =(unsigned char *)(DD_BASE + PLAYFIELD_DATASTREAM);

The C code can update the datastream by setting values like gPlayer0Datastream[0] = 1, gPlayer0Datastream[10]=5, and so on. The routine that updates the datastream to create the above display is this:

 

 

void SetTestValues()
{
    int i;
    // first 5 are the reposition scanlines, not used for gameplay
    for(i=0;i<5;i++)
    {
        gPlayer0Datastream[i]   = 0xff;
        gPlayer1Datastream[i]   = 0xff;
        gMissile0Datastream[i]  = 0x0f;
        gMissile1Datastream[i]  = 0x0f;
        gBallDatastream[i]      = 0x0f;
    }
    
    // gameplay area is 160 scanlines
    for(i=5;i<DATASTREAM_SIZE;i++)
    {
        gPlayer0Datastream[i]   = i-5;
        gPlayer1Datastream[i]   = i-5;
        gMissile0Datastream[i]  = (i-5) & 0x0f;
        gMissile1Datastream[i]  = (i-5) & 0x0f;
        gBallDatastream[i]      = (i-5) & 0x0f;
    }
}

 

The last thing your custom C code does is configure the BUS Stuffing Driver so it knows which of the 16 datatream is used for which TIA register(s). Yes, a single stream can be used by more than 1 register, it can also be used by RAM addresses. This is the C code which does that:

void SetDatastreams()
{
//    ;   0 = 6507 <--> ARM 
//    ;   1 = GRP0 & HMP0
//    ;   2 = GRP1 & HMP1
//    ;   3 = ENAM0 & HMM0
//    ;   4 = ENAM1 & HMM1
//    ;   5 = ENABL & HMBL
//    ;   6 = COLUPx for player being repositioned
//    ;   7 = NUSIZx for player or missile being repositioned
//    ;   8 = NextKernel datastream
    
    // do a test to see if setPointer() is optimized away
    QPTR[1]             = PLAYER0_DATASTREAM << 20;     // GRP0 & HMP0
    QPTR[2]             = PLAYER1_DATASTREAM << 20;     // GRP1 & HMP1
    QPTR[3]             = MISSILE0_DATASTREAM << 20;    // ENAM0 & HMM0
    QPTR[4]             = MISSILE1_DATASTREAM << 20;    // ENAM1 & HMM1
    QPTR[5]             = BALL_DATASTREAM << 20;        // ENABL & HMBL
    QPTR[6]             = COLOR_DATASTREAM << 20;       // COLUP0, COLUP1 & COLUPF
    QPTR[7]             = SIZE_DATASTREAM << 20;        // NUSIZ0 & NUSIZ1
    QPTR[8]             = JUMP_DATASTREAM << 20;        // ZP RAM NextKernel
    QPTR[9]             = SCORE_DATASTREAM << 20;       // Score/Radar/Lives/Formation display
    
    
    
    // do a test to see if setMapping() is optimized away
    QMAP[QUEUE_GRP0]            = 0x11111111;
    QMAP[QUEUE_HMP0]            = 0x11111111;
    QMAP[QUEUE_GRP1]            = 0x22222222;
    QMAP[QUEUE_HMP1]            = 0x22222222;
    QMAP[QUEUE_ENAM0]           = 0x33333333;
    QMAP[QUEUE_HMM0]            = 0x33333333;
    QMAP[QUEUE_ENAM1]           = 0x44444444;
    QMAP[QUEUE_HMM1]            = 0x44444444;
    QMAP[QUEUE_ENABL]           = 0x55555555;
    QMAP[QUEUE_HMBL]            = 0x55555555;
    QMAP[QUEUE_COLUP0]          = 0x66666666;
    QMAP[QUEUE_COLUP1]          = 0x66666666;
    QMAP[QUEUE_COLUPF]          = 0x66666666;
    QMAP[COLOR & 0x3f]          = 0x66666666;   // ZP RAM 0x82
    QMAP[QUEUE_NUSIZ0]          = 0x77777777;
    QMAP[QUEUE_NUSIZ1]          = 0x77777777;
    QMAP[SIZE & 0x3f]           = 0x77777777;   // ZP RAM 0x83
    QMAP[NEXT_KERNEL & 0x3f]    = 0x88888888;   // ZP RAM 0x80
    QMAP[QUEUE_PF0]             = 0x99999999;
    QMAP[QUEUE_PF1]             = 0x99999999;
    QMAP[QUEUE_PF2]             = 0x99999999;
    
    // do a test to see if setIncrement() is optimized away
    QINC[0]             = 0x100;    // 1.0
    QINC[1]             = 0x100;    // 1.0  GRP0 & HMP0
    QINC[2]             = 0x100;    // 1.0  GRP1 & HMP1
    QINC[3]             = 0x80;     // 0.5  ENAM0 & HMM0
    QINC[4]             = 0x80;     // 0.5  ENAM1 & HMM1
    QINC[5]             = 0x80;     // 0.5  ENABL & HMBL
    QINC[6]             = 0x100;    // 1.0  COLUP0, COLUP1 & COLUPF
    QINC[7]             = 0x100;    // 1.0  NUSIZ0 & NUSIZ1
    QINC[8]             = 0x100;    // 1.0  NextKernel
    QINC[9]             = 0x100;    // 1.0  Score/Radar/Lives/Formation
}


The addresses are limited to $00-$24 for TIA and $80-$A4 for RAM.

 

 

When BUS Stuffing is turned on, the BUS Driver monitors for the STY zero page instructions. When it sees one it uses the values in QMAP to figure out which datastream to pull the data from. That data is then stuffed onto the bus at the appropriate time. Finally the datastream is advanced by the increment amount.

 

 

 

The ARM is timed to copy the registers (bus stuff) to the data bus when it intercepts the STY command. It does this continually so the game never rolls or bounces.

It only intercepts the STY command when BUS Stuffing is turned on. Once your kernel is done you turn it off:

 

        ldx #$FF
        stx STUFFMODE ; non-zero turns off bus stuffing   

Then, like normal, the 6507 code takes care generating the sync signal at the appropriate time so the picture doesn't roll or bounce.

 

The 6507 stores the Y register depending on what data was on the bus. Updating TIA and playfield and sprite information.

The BUS Driver overrides the $FF value contained in the Y register when the 6507 goes to update the playfield (STY PF0, STY PF1, STY PF2) or sprite information (STY GRP0, STY COLUP0, STY NUSIZ0, etc).

 

In this arrangement, the 6507 is really just a bus driver and the ARM does all the logic and memory manipulation. That's how you can program your game in C!

The 6507 coordinates when and what to update. The ARM is the bus driver during the kernel. During overscan and vertical blank the 6507 will use the ARM as a co-processor for the game logic and memory manipulation, the ARM is not a bus driver during that time. This is just like your computer's CPU can offload calculations to your GPU. If your GPU is faster than your CPU at running certain routines then it makes sense to offload those routines to the GPU.

 

The Harmony cartridge implementation differs in that it stores a compiled binary in flash. It watches the address lines and then fetches data from a flash location and outputs that on the data bus. Sort of like a normal cartridge but with the benefits of not having to program an EPROM.

That's correct for the "ROM" emulation.

 

In this implementation, how do you get input information from the Atari RIOT? You can write data to the Atari, but how do you read joysticks and paddles?

The 6507 can write to the datastreams. In Draconian I have this datastream:

ARMsub:             ds 1    ; Which ARM subroutine to run:
                            ;       0 = Initialize()
                            ;       1 = OverScan()
                            ;       2 = VerticalBlank()
                            ;       3 = SetDatastreams()
ARMswcha:           ds 1    ; controller input to ARM
ARMswchb:           ds 1    ; console switches to ARM
ARMinpt4:           ds 1    ; left player firebutton
ARMinpt5:           ds 1    ; right player firebutton
ARMvbtime:          ds 1    ; time remaining in Vertical Blank
ARMostime:          ds 1    ; time remaining in Overscan
ARMframe:           ds 1    ; return value from call to OverScan

which is used like this for the joystick, console switches, etc:

        ; prep for call to OverScan()
        ldx #>ARMsub    ; 2 40
        stx DS0PTR
        ldx #<ARMsub    ; 2 30
        stx DS0PTR      ; 4 34
        ldx #RUN_OS     ; run = OverScan();
        stx DS0WRITE    ; 3 
        ; pass the PIA and TIA registers to the ARM code
        ldx SWCHA       ; 4 
        stx DS0WRITE    ; 4 
        ldx SWCHB       ; 4 
        stx DS0WRITE    ; 4 
        ldx INPT4       ; 3 
        stx DS0WRITE    ; 4 
        ldx INPT5
        stx DS0WRITE
        ldx VBtime
        stx DS0WRITE
        ldx OStime
        stx DS0WRITE
        ldx #$FF
        stx CALLFN  ; tells the ARM code to run OverScan()
        lda DS0DATA
        sta Frame       
  • Like 3
Link to comment
Share on other sites

  • 1 month later...

The 7800's notorious for compatibility issues and my 7800 wouldn't run the Bus Stuffing demos.

 

batari provided input on what he had to do with DPC+ to get it to work with 7800s like mine. Chris used that information and updated the Bus Driver. I built new versions of the RPG demo, which my 7800 can now run:

post-3056-0-95200400-1483206575_thumb.jpg

rpg_20161231_NTSC.bin

rpg_20161231_PAL.bin

  • Like 4
Link to comment
Share on other sites

Is that information in the forum somewhere? Can it be?

 

batari said it had to do with the evil 7800's pulling A12 low for part of a cycle, and if the ARM sees that it erroneously thinks the address changed. This bit of code in the bus driver:

 

/* Wait for address change */
Transmit:
  ldrh    r2, [r0, #+0x16]
WaitAddressChange:
  ldrh    r1, [r0, #+0x16]
  cmp     r2, r1
  beq     WaitAddressChange


was changed to this in order to ignore A12:

/* Wait for address change */
Transmit:
  ldrh    r2, [r0, #+0x16]
  mov     r2, r2, asl #21
WaitAddressChange:
  ldrh    r1, [r0, #+0x16]
  cmp     r2, r1, asl #21
  beq     WaitAddressChange


  • Like 1
Link to comment
Share on other sites

Interesting, I didn't know that 7800s do that. That A12 behavior isn't limited to the 7800 though. I have a 2600 Jr. that does the same thing. Of course the 6502 datasheet agrees with this behavior since the address bus is only guaranteed to be valid at specific portions of each cycle. Sure would be nice if some of the control bus had made its way to the cartridge...

 

Have you changed your mind about supporting quad-stuffing yet? Regarding PAL vs NSTC, can't you just time how long it takes to execute some arbitrary routine and load the appropriate driver accordingly?

Link to comment
Share on other sites

The 7800's notorious for compatibility issues and my 7800 wouldn't run the Bus Stuffing demos.

 

batari provided input on what he had to do with DPC+ to get it to work with 7800s like mine. Chris used that information and updated the Bus Driver. I built new versions of the RPG demo, which my 7800 can now run:

attachicon.gifIMG_8182.jpg

attachicon.gifrpg_20161231_NTSC.bin

attachicon.gifrpg_20161231_PAL.bin

Sweet. I gotta try these out... :grin:

Link to comment
Share on other sites

Sure would be nice if some of the control bus had made its way to the cartridge...

Very true

 

Have you changed your mind about supporting quad-stuffing yet?

It's still on the back burner while we flesh out what we have working. Not much progress of late due to the holidays - Chris' driver update that fixed my 7800 was done back on the December 11th, and only now have I had the time to try it out.

Link to comment
Share on other sites

A few changes to the 128 Chronocolor demo:

  • new Bus Driver in place so it now works on my 7800
    post-3056-0-47309500-1483290335_thumb.jpg
  • now starts with 262 scanlines, so it should [initially] work on all displays without rolling
    post-3056-0-62443100-1483290330_thumb.png
  • If you hold down the firebutton the scanline count will change slower

 

As before:

  • Left Difficulty=A for PAL, B=NTSC
    NOTE: This is only checked during the init process, so you'll have to power-cycle the console to change between NTSC and PAL.
  • change scanline count using joystick up/down

128chronocolour_20170101.bin

Link to comment
Share on other sites

It's possible that VBs running a little longer than before as it creates the RGB picture on the fly and the picture now starts out 22 scanlines taller than before.

 

Here's a quick test with an extra scanline output after VB ends:

128chronocolour_20170101b.bin

 

If that fixes the problem then decreasing the screen size will cause the scanline count to become odd at some point, so I'll have to come up with a better solution.

Link to comment
Share on other sites

Changes for the 128 pixel demo:

  • updated Bus Driver, now runs on my 7800. I'm hoping this fixes the extra vertical lines alex_79 was seeing
  • updated kernel to support 2 HMP0 values instead of only $B0
  • migrated the auto-detect of HMP0 value needed for alex_79's systems
  • removed the chronocolour demo
  • added display of time remaining for Vertical Blank and Overscan to the 32 character demo. VB was out of time!
  • optimized the reverse field routines to fix VB overrun

post-3056-0-92141200-1483388871_thumb.jpg

 

Right Difficulty controls color of player0.

128bus_20170102.bin

  • Like 2
Link to comment
Share on other sites

I finally tested the updated demos posted in the last couple of weeks on my 7800 and my Light Sixer.

Unfortunately my 7800 still shows extra vertical lines. Apparently bus-stuffing doesn't work correctly on my machine and bit 7 on the data bus seems to always be set.

rpg_20161231_PAL:

 

7800:

post-10599-0-77034400-1483982426_thumb.jpg

2600:

post-10599-0-48514100-1483982429_thumb.jpgpost-10599-0-79954700-1483982432_thumb.jpg

-------------------------------------------------------
parrot_20161231_PAL:

7800:

post-10599-0-32211200-1483982422_thumb.jpg

2600:

post-10599-0-78839700-1483982424_thumb.jpg

--------------------------------------------------------
test_20161231:

7800:

post-10599-0-68685500-1483982435_thumb.jpg

2600:

post-10599-0-71109200-1483982438_thumb.jpg

--------------------------------------------------------
128chronocolour_20170101:

7800:

post-10599-0-17882500-1483982321_thumb.jpg

2600:

post-10599-0-51861900-1483982331_thumb.jpg

--------------------------------------------------------
128chronocolour_20170101b:

7800:

post-10599-0-50854200-1483982324_thumb.jpg

2600

post-10599-0-04983100-1483982328_thumb.jpg

 

--------------------------------------------------------
128bus_20170102:
7800:

post-10599-0-82333000-1483982229_thumb.jpgpost-10599-0-38286100-1483982232_thumb.jpgpost-10599-0-86100500-1483982235_thumb.jpgpost-10599-0-57828700-1483982239_thumb.jpg

2600:

post-10599-0-24697900-1483982243_thumb.jpgpost-10599-0-06393200-1483982245_thumb.jpgpost-10599-0-66324200-1483982248_thumb.jpgpost-10599-0-48207200-1483982252_thumb.jpg

Link to comment
Share on other sites

Bummer, don't know what else could be going on. I'll drop a note to batari to see if he has any ideas.

 

The auto-detect for the different HMM0 value appears to be working. Does the text demo still do the color change if you have the right difficulty set to B? I'm hoping the reverse field optimizations cleared that up.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...