Shop Learn
Console Emulation - Page 6 — Parallax Forums

Console Emulation

13468916

Comments

  • Well, at least I figured out why the opponent in the Pong ROM didn't move (incorrect Z flag from NOT.B/NOT.W)

  • Wuerfel_21Wuerfel_21 Posts: 2,485
    edited 2021-12-28 02:57

    Since I don't even know where to begin to debug the symptoms in Flicky, I turned my attention to simpler aspirations once again. Introducing, the SGDK hello world example. This is interesting, because it is literally just printing hello world, but to get there, it has to pass through the nine circles of hell SGDK bloat.

    Interesting behavioral difference: the precompiled ROM that comes with SGDK ends up printing a (slightly cut off) error message about being out of memory (as seen in the library source here), but building the example from scratch ends up with a register dump and a message that a CHK had tripped at $0000010A (-> inside the ROM header). Investigation (read: looking confusedly at call logs and disassemblies for hours before finally looking at the implementation of SYS_die) reveals that SYS_die calls VDP_Init, resulting in infinite recursion if VDP_Init keeps failing, which eventually leads to the stack creeping into the heap and getting corrupted. Why the prebuilt version doesn't do this is a mystery. Eitherhow, as the previously linked source reveals, the only thing that could fail is loading the font, which in itself is obviously successful, as otherwise the error messages wouldn't be visible. In other words, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa this is so difficult to debug. As far as I can tell, the unpack routine does its thing, but returns zero anyways, because lol. But that should lead to the font never actually being written to VRAM, which it clearly is???

    (Correction: It does seem that the unpack properly returns a non-null pointer on the first invocation (from which the data is then copied to VRAM), I was just looking into the middle of the logs, so that mystery is at least laid to rest)

  • Wuerfel_21Wuerfel_21 Posts: 2,485
    edited 2021-12-29 21:19

    Well, I have stared into the abyss and the abyss stared back. And then it pointed me to these 3 instructions:

        496a:   4240            clrw %d0
        496c:   3210            movew %a0@,%d1
        496e:   6724            beqs 4994 <MEM_alloc+0xac>
    

    In non-ludicrous syntax, that's

    clr.w d0
    move.w (a0),d1
    beq somewhere
    

    So we want to clear D0, load the word pointed to by A0 into D1 and then branch somewhere if we got zero.
    ...
    What actually happens is that despite loading a non-zero value into D1, the move doesn't actually clear the zero flag and it just branches, anyways.

    Here is that happening in real time (pay mind that the PC values are all +2 because they're being printed after reading the opword. Also note that Z is bit 2 of SR)

    Cog4  got op: mk_opword = $4240 before mk_virtualpc = $0000_496C, mk_sr = %00001000, mk_a0 = $E0FF_0A68, mk_d1 = $0000_0C08, #((&main_ram) + 2664) = $0305
    ; ^^ This is the CLR D0. As you can see, Z is set in the next line
    Cog4  got op: mk_opword = $3210 before mk_virtualpc = $0000_496E, mk_sr = %00000100, mk_a0 = $E0FF_0A68, mk_d1 = $0000_0C08, #((&main_ram) + 2664) = $0305
    ; ^^ this is the MOVE (A0),D1. As you can see, the value is correctly being loaded into D1, but the Z flag remains set
    Cog4  got op: mk_opword = $6724 before mk_virtualpc = $0000_4970, mk_sr = %00000100, mk_a0 = $E0FF_0A68, mk_d1 = $0000_0503, #((&main_ram) + 2664) = $0305
    ; ^^ This is the BEQ - branch is erroneously taken
    Cog4  got op: mk_opword = $4A40 before mk_virtualpc = $0000_4996, mk_sr = %00000100, mk_a0 = $E0FF_0A68, mk_d1 = $0000_0503, #((&main_ram) + 2664) = $0305
    

    "But Ada, why don't you just fix the Z flag for MOVE, then?"
    Because it already should work! This is the relevant code:

    mk_nibble_3 ' MOVE (word)
                  'debug("in move.w")
                  callpb mk_opword,#mk_setup_operand16
                  call mk_readf
                  callpa #15,#mk_move_shoot_the_shit
                  callpb mk_opword,#mk_setup_operand16
                  'debug("in move.w, writing ",uhex_word(mk_memvalue)," to ",uhex_long(mk_effaddr))
                  jmp mk_writef
    
    mk_move_shoot_the_shit ' handle all the common MOVE stuff
                   ' Doing MOVEA?
                  test mk_opword,#%110_000_000 wz
                  testb mk_opword,#9 andz
            if_z  jmp #.movea
                  signx mk_memvalue,pa wcz
                  bitc mk_sr,#MK_NEG_BIT
                  bitz mk_sr,#MK_ZERO_BIT
                  andn mk_sr,#MK_OVER_MASK|MK_CARRY_MASK
    .mangle_ea2   ' format for second operand is stupid
                  setnib mk_opword,#0,#3
                  mov pa,mk_opword
                  and pa,#%111_000_000
                  shl pa,#6
                  or mk_opword,pa
            _ret_ shr mk_opword,#9
    

    The part of interest is around the SIGNX, which is used to check for negative and zero values. mk_memvalue must be correct at this point, otherwise it wouldn't work at all. I've looked over this a bunch and can not find the bug.

    Well, can only dig deeper for the needle in the mountain of hay.

  • Wuerfel_21Wuerfel_21 Posts: 2,485
    edited 2021-12-29 21:35

    And of course, immediately upon posting, I realize the errors of my ways.

                   ' Doing MOVEA?
                  test mk_opword,#%110_000_000 wz
                  testb mk_opword,#9 andz
            if_z  jmp #.movea
    

    I'm pretty sure I meant to test bit 6. Bit 9 would be... wether the target register is odd-numbered? Ye, checks out.

    Sadly, this nugget of enlightenment does not get us any closer to seeing that sweet SGDK hello world (it now just gives a blank screen on either version), but it does seem to fix the scrambled map in Flicky. Still hangs after Flicky comes through the door. Also, none of the other commercial games do anything yet except clear CRAM.

    I have a hunch though that all these may be trying to acquire the audio bus lock, so I'll just implement that real quick.

  • Well, implementing the audio bus lock made the SGDK hello world happy, at least. Commercial games are still not impressed (though Columns seems to be running its VBlank IRQ and polling it in there, so that's something?).

    Though the SGDK-provided funtime isn't over. The next most advanced sample tries to display an image, once as a compressed asset and once as an uncompressed one. Guess which one gets corrupted? The uncompressed one, of course. (As seen with the font from the hello world sample, the decompression routine just works for some reason)

  • Ok, that one was just ROM->VRAM DMA being totally busted and "sadly" not a 68000 bug.

  • Wuerfel_21Wuerfel_21 Posts: 2,485
    edited 2022-01-01 03:32

    Well, here's something for new years:

    Changes:
    - Fix indexed addressing modes in 68000 core (word-sized index was treated as long-sized index and vice-versa)
    - Implement VRAM fill
    - Only do endian swap when writing to odd VRAM addresses (ignore for CRAM/VSRAM)
    - Allow setting console region (see constants near the top of megayume_lower.spin2)
    - Include columns.bin ROM. For purely educational/research purposes. No seriously, the game is a bit boring.

  • TubularTubular Posts: 4,452
    edited 2022-01-01 05:05

    Oh thats pretty exciting, well done Ava Ada

  • roglohrogloh Posts: 4,024
    edited 2022-01-01 02:43

    Got it displaying video, it looks cool. Can't wait for the sound to be added too.

    My USB keyboard doesn't seem to be responding in the game itself if that part is meant to work too. Might be incompatibility with the USB driver as you seem to be using the newer version, though I do know this particular keyboard does with with the older version of garryj's USB driver. I have flex 5.9.3 too which might have made a difference here perhaps.

    EDIT: silly me, need to fit the 5V ACC jumper.

  • @rogloh said:
    Got it displaying video, it looks cool. Can't wait for the sound to be added too.

    The way it's going, PSRAM for larger ROMs will probably come before Z80 (and thus, sound). Though most games need both. There's also still something afoot with the 68000, SGDK's 3D cube example still doesn't work (though it is what I analyzed to find the addressing mode bug, so finding the other one should be easier since I already have identified most of the trace noise).

    EDIT: silly me, need to fit the 5V ACC jumper.

    Happens to the best of us.

    @Tubular said:
    Oh thats pretty exciting, well done Ava

    It's Ada, with a D.

  • TubularTubular Posts: 4,452

    It's Ada, with a D.

    My apologies, corrected

  • roglohrogloh Posts: 4,024
    edited 2022-01-01 05:26

    @Wuerfel_21 said:
    The way it's going, PSRAM for larger ROMs will probably come before Z80 (and thus, sound).

    Sounds good.

    Do you plan to incorporate your own memory reading code in your own COG first or start out with my own driver at the beginning to experiment with the memory? I'm thinking you could always use it to get the external memory loaded with a good known ROM state first for testing your own reader code.

    One good thing about your own ROM expansion application is that you don't need to worry about the byte masking during byte/word writes, which my driver needed to do, and the maximum CS low time will not be an issue for your shorter reads so no real need for any fragmentation (beyond page boundaries perhaps).

  • ColeyColey Posts: 1,101

    Way to go Ada, this is fantastic work :smile:

  • BaggersBaggers Posts: 3,018

    This is awesome Ada, well done, and Happy New Year :D

  • @rogloh said:

    @Wuerfel_21 said:
    The way it's going, PSRAM for larger ROMs will probably come before Z80 (and thus, sound).

    Sounds good.

    Do you plan to incorporate your own memory reading code in your own COG first or start out with my own driver at the beginning to experiment with the memory? I'm thinking you could always use it to get the external memory loaded with a good known ROM state first for testing your own reader code.

    Ye, will use your driver to initialize the memory bank and preload the ROM (256k at a time...). Eventually needs a little menu system to select ROMs to load from SD card.

    @Baggers said:
    This is awesome Ada, well done, and Happy New Year :D

    Thanks. And I just realize I completely forgot about doing the Spin Hexagon 8in1 thing, lol.

  • Here's another version...

    • Reworked handling of address register operations to fix CMP.W An,Dn (and probably others?)
    • Fixed DIVU/DIVS (owie ouch)
    • Implemented HBlank interrupt

    This is now good enough to run SGDK's 3D cube example, as well as the scaling/wobble H-Interrupt trick examples.
    There's still bugs left I want to fix before I add any more features.

  • This 68k- Emulator is very impressing for me!
    I have been wondering, if it would be useful to have an operating system. Long time ago I worked wit OS9/69k on a VME-Bus system with 68020 controlling a test rig. OS9 would be nice, because it has multitasking. It looks, if emulating a 68k would make some sense for a self-hosted system, because then a system with 512kB as in P2 now was sufficient. Unfortunately only for 6809 there is Nitros as a free version of OS9.

  • @"Christof Eb." said:
    This 68k- Emulator is very impressing for me!
    I have been wondering, if it would be useful to have an operating system. Long time ago I worked wit OS9/69k on a VME-Bus system with 68020 controlling a test rig. OS9 would be nice, because it has multitasking. It looks, if emulating a 68k would make some sense for a self-hosted system, because then a system with 512kB as in P2 now was sufficient. Unfortunately only for 6809 there is Nitros as a free version of OS9.

    You could probably run some sort of OS on the 68000 core (when I'm done fixing the bugs...), all the functionality is there. Though the information pushed onto the stack by the various error/exception conditions may not always be terribly accurate. This is probably fine for games where the exception handlers don't do anything useful, but may be an issue for more advanced systems.

  • Wuerfel_21Wuerfel_21 Posts: 2,485
    edited 2022-01-03 03:22

    Come closer, ladies, gentlemen and beings inbetween, for it is time to once again play my favorite game:

    SPOT THE REALLY STUPID MISTAKE!!!

    Can you see it?

    A shift amount of zero (only possible when sourced from a register) is a special case that needs, well, special care.
    There's two bugs here, a major and a minor one. The major one being that the routine tail calls through mk_writef, but if do_shift is skipped, mk_readf was never called, so the operand is overwritten with whatever the previous instruction's result was.
    The second bug is more subtle: ROXL and ROXR need to set the carry flag equal to the extend flag when performing a zero-bit shift. Not sure if anything ever relies on this obscure behavior, but I noticed it while reviewing the manual entries for the shift operations.

    Eitherhow, with this nonsense patched up, Ishido: The Way of Stones boots up, but is unplayable because it seems to have trouble reading the controller (A and START ignored, as if the select line was permanently high).

    Yet still, there are more CPU bugs abound. None of the other stubbornly blackscreening ROMs seem impressed by this fix. Round timer in Flicky still doesn't work.

  • roglohrogloh Posts: 4,024
    edited 2022-01-03 03:29

    Is there a way to test your 68k emulator completeness without playing a game to find any remaining bugs? Are there any CPU opcode tests you could use?

  • Wuerfel_21Wuerfel_21 Posts: 2,485
    edited 2022-01-03 03:49

    Not that I'm aware of. There exists one test, but it is designed to run from RAM and doesn't have any output other than getting stuck on a given address.

    Note that I don't actually find CPU bugs by playing the games, that'd be nigh impossible. My methodology is to find one that doesn't boot up at all and log the first hundred thousand or so executed instructions into a file. Then I do the same in BizHawk. Then I run a little script to process both logs into lines containing just the PC (and also remove noise such as waiting on the VDP status register), which I can then diff to figure out where the metaphorical train jumps off the rails, which gives the first lead on what instruction may be misbehaving. With the presumably-decompression-idk routine that was preventing Ishido from booting, this was slightly more complicated, since the routine branches around a fair bit and doesn't fail on the first iteration.

    Infact, here's the disassembled routine. The branch that went wrong is the one at 1D6C. Can you figure out how it even gets there? And where does D4 come from? And what is it trying to accomplish? Tricky stuff.

        1d30:   48e7 f810       moveml %d0-%d4/%a3,%sp@-
        1d34:   2c18            movel %a0@+,%d6
        1d36:   2e18            movel %a0@+,%d7
        1d38:   3a18            movew %a0@+,%d5
        1d3a:   2448            moveal %a0,%a2
        1d3c:   2648            moveal %a0,%a3
        1d3e:   2007            movel %d7,%d0
        1d40:   6b08            bmis 0x1d4a
        1d42:   4840            swap %d0
        1d44:   e340            aslw #1,%d0
        1d46:   d6c0            addaw %d0,%a3
        1d48:   4840            swap %d0
        1d4a:   4a86            tstl %d6
        1d4c:   6a0c            bpls 0x1d5a
        1d4e:   204b            moveal %a3,%a0
        1d50:   224b            moveal %a3,%a1
        1d52:   e340            aslw #1,%d0
        1d54:   d0c0            addaw %d0,%a0
        1d56:   6000 0088       braw 0x1de0
        1d5a:   41f9 ffff 0000  lea 0xffff0000,%a0
        1d60:   4a40            tstw %d0
        1d62:   6b44            bmis 0x1da8
        1d64:   4241            clrw %d1
        1d66:   4242            clrw %d2
        1d68:   602c            bras 0x1d96
        1d6a:   e39c            roll #1,%d4
        1d6c:   651a            bcss 0x1d88
        1d6e:   e29c            rorl #1,%d4
        1d70:   4844            swap %d4
        1d72:   30c4            movew %d4,%a0@+
        1d74:   3604            movew %d4,%d3
        1d76:   2813            movel %a3@,%d4
        1d78:   544b            addqw #2,%a3
        1d7a:   0a41 0007       eoriw #7,%d1
        1d7e:   e3bc            roll %d1,%d4
        1d80:   e3bc            roll %d1,%d4
        1d82:   0a41 0007       eoriw #7,%d1
        1d86:   601c            bras 0x1da4
        1d88:   e39c            roll #1,%d4
        1d8a:   6504            bcss 0x1d90
        1d8c:   30c3            movew %d3,%a0@+
        1d8e:   6006            bras 0x1d96
        1d90:   30c2            movew %d2,%a0@+
        1d92:   3602            movew %d2,%d3
        1d94:   5242            addqw #1,%d2
        1d96:   51c9 000c       dbf %d1,0x1da4
        1d9a:   4a40            tstw %d0
        1d9c:   670a            beqs 0x1da8
        1d9e:   7207            moveq #7,%d1
        1da0:   2813            movel %a3@,%d4
        1da2:   544b            addqw #2,%a3
        1da4:   51c8 ffc4       dbf %d0,0x1d6a
        1da8:   2248            moveal %a0,%a1
        1daa:   3005            movew %d5,%d0
        1dac:   7405            moveq #5,%d2
        1dae:   4a46            tstw %d6
        1db0:   6a02            bpls 0x1db4
        1db2:   7402            moveq #2,%d2
        1db4:   e560            aslw %d2,%d0
        1db6:   141b            moveb %a3@+,%d2
        1db8:   6b0c            bmis 0x1dc6
        1dba:   4882            extw %d2
        1dbc:   9042            subw %d2,%d0
        1dbe:   12db            moveb %a3@+,%a1@+
        1dc0:   51ca fffc       dbf %d2,0x1dbe
        1dc4:   6010            bras 0x1dd6
        1dc6:   4402            negb %d2
        1dc8:   6bec            bmis 0x1db6
        1dca:   4882            extw %d2
        1dcc:   9042            subw %d2,%d0
        1dce:   161b            moveb %a3@+,%d3
        1dd0:   12c3            moveb %d3,%a1@+
        1dd2:   51ca fffc       dbf %d2,0x1dd0
        1dd6:   5340            subqw #1,%d0
        1dd8:   66dc            bnes 0x1db6
        1dda:   43f9 ffff 0000  lea 0xffff0000,%a1
        1de0:   0886 001f       bclr #31,%d6
        1de4:   0886 000f       bclr #15,%d6
        1de8:   4cdf 081f       moveml %sp@+,%d0-%d4/%a3
        1dec:   4e75            rts
    

    The numbers, Mason, what do they mean???

  • roglohrogloh Posts: 4,024
    edited 2022-01-03 04:01

    First google search hit this. Is this link below of any use? You might need an assembler too. Perhaps this is the one you already mentioned...

    https://microcorelabs.wordpress.com/2020/07/14/mcl68-test-code-uploaded/

  • Wuerfel_21Wuerfel_21 Posts: 2,485
    edited 2022-01-03 15:47

    @rogloh said:
    First google search hit this. Is this link below of any use? You might need an assembler too. Perhaps this is the one you already mentioned...

    https://microcorelabs.wordpress.com/2020/07/14/mcl68-test-code-uploaded/

    Yeah, I found that one, but
    a) it's written in a really strange assembly syntax that I can't easily translate
    b) it expects RAM at $000100 and these addresses are hardcoded. I'd have to fork off a separate version with RAM only. But that wouldn't catch any bugs related to the interplay of instructions and bus I/O.

    IDK, I guess I just prefer the goal-oriented workflow for this in particular.

    Eitherhow, I figured out why the controls didn't work in Ishido: IO access didn't work when accessed with the top byte of the address non-zero. It was trying to write to $01A10009 to set the direction register for player 1's IO port and that didn't work, so it couldn't ever read A/START.

    So to that there's now a total of 3 confirmed working games:
    - Flicky (bug: round timer always zero)
    - Columns
    - Ishido

    Funny trivia about Ishido I found out while procrastinating: It's framed as a forgotten old asian board game, right? It really isn't, it was designed by some guy in America as a computer game. According to this unsourced claim in the Wikipedia article for the game, there was a physical version published in Japan (By the big brains at ASCII, nontheless). But there seems to exist no evidence other than this one article for that actually having been a thing. So, it seems like it went full circle and has now actually become a forgotten old asian board game (if 1992 counts as old, that is). Mental.

    Eitherhow, here's a ZIPful of bugfix.

  • Wuerfel_21Wuerfel_21 Posts: 2,485
    edited 2022-01-03 17:54

    Well, figured why Ms. Pacman doesn't work: It does some... Interesting things with the HV counter. Like, the selection cursor on the menu screen is drawn by polling the counter in a loop and setting the background color. Once again, MENTAL. As is this VBlank wait routine:

    Then again, if I rig the counter to return random values, it doesn't get stuck anymore, but Ms. Pacman seems to have gained the ability to eat the walls of the maze. Annoyingly, the ghosts can also phase through the walls:)

  • Hmm, problem is that @rogloh 's video driver does not actually count blanking lines, so I can't accurately return the V counter value (not to speak of the H counter, but that one is only really useful for lightgun stuff)

    Time to write new video code from scratch, then. Owie ouch. Though that will also solve the issue with switching H40/H32 and 240p/480i on the fly.

  • roglohrogloh Posts: 4,024
    edited 2022-01-03 23:01

    I could look at a counter for blanking. In the meantime you might be able to monitor the HSYNC pin transitions yourself (in VGA mode anyway).

    In the past I've also considered adding a COGATN mechanism for indicating the HSYNC to COGs (which COGs get notified would need to be indicated at driver startup). I think it could potentially be done, but I know that fitting that in while also operating in PAL output mode is going to be a problem unless I jump out to HUBEXEC mode or something and I don't know if I have the cycles.

  • evanhevanh Posts: 12,885
    edited 2022-01-03 23:36

    Roger,
    The graphics driver is sounding just too constrained by cogRAM now. Might be time to consider it being multiple components that the application developer selects from, instead of trying to keep it as one blob.

  • roglohrogloh Posts: 4,024

    @evanh said:
    Roger,
    The graphics driver is sounding just too constrained by cogRAM now. Might be time to consider it being multiple components that the application developer selects from, instead of trying to keep it as one blob.

    A dilemma.

    So far it's been developed as a universal driver, with any feature on any output type which is great. Splitting it up can lose that. Also official SPIN2 doesn't really have a good way to include what you want except by doing things at a coarse file level - which means multiple duplicate files with lots of combinations to maintain - nasty. On the other hand it could possibly free a couple more COGRAM longs if PAL/NTSC sync is removed, or a lot more if things like mouse, or text cursors, or external RAM, or LUT8 mode etc, etc can get dropped by choice. I'm just not sure I'm ready to go down that path yet and it creates far more complexity for me in testing it too.

  • evanhevanh Posts: 12,885

    Might be a good point in time for Chip and Eric and Ross to work out a solution. Your driver won't be the only one to benefit.

  • Wuerfel_21Wuerfel_21 Posts: 2,485
    edited 2022-01-04 22:33

    Well, I spun up a basic VGA driver that does count blanking lines (in a particular way I can benefit from, too), but it seems to make the VDPR sad, it seems to go on a mad spree of writing zeroes everywhere... The only interface between video driver and the VDP cogs is the line counter, so IDK what stupid issue it is this time.

    EDIT: Okay, that was just a latent bug where the render code could be executed without certain variables getting initialized. However, games are still broken and IDK why. Flicky works. No idea why, but it does. No idea why everything else is broken, either.

    EDIT 2: Report from the trenches: Actually fixing the V counter makes Ms. Pacman boot, but it crashes the entire P2 when starting a game. Cool. (Remember, it worked previously with randomized V counter, but you could go through walls unimpeded)

    EDIT 3: Well, I've got to a point where I have the good old "mysteriously starts working with debug enabled". Sigh.

    EDIT 4: Yep, it's the real good stuff: Works with only DEBUG enabled, even if all the actual DEBUGs are commented out. So it goes ham because of the debugger not being there? ???? ??? Well, I at least could find out why Ms. Pacman goes through walls. I never implemented VRAM read and apparently it actually uses that for the game logic. Odd choice, but should work once I actually implement it. Yea, lets do that instead of figuring out the crash bug, yea.

    EDIT 5: Yes, VRAM read makes Ms. Pacman work as intended. Weirdly, this game is actually broken on Exodus. Like, sike?
    Still no idea what causes the strange issues. I do see some minor corruptions in Columns' graphics when it does work under DEBUG, so I think the issue manifests in corrupting the ROM in memory and when it hits code instead of data, that makes it go sad. Filling high RAM with $FF doesn't seem to make a difference, so IDK what causes the bug to appear, still.

Sign In or Register to comment.