Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - JetSetIlly

#1
Programming / FROB-26
10 Mar 2025, 06:14 PM
The FROB-26 working after some restoration. I think this is @thom.cherryhomes work

https://www.youtube.com/watch?v=IAefPk7WgJk
#3
General Discussion / Atari 2600 Encylopedia
13 Feb 2025, 08:01 AM
Saw this on itch.io. It's a few years old but I've not seen it before. It's nicely done I think.

https://daddarulekonge.itch.io/apro
#4
Gopher 2600 / v0.40.0-preview
14 Jan 2025, 08:34 AM
I've written comprehensive release notes on the github page. But just to emphasise, this is a "preview" release of some major changes.

It's a "preview" because there are some changes that have not yet finalised - the default colour palette. However, I think the project would benefit if people can have a look at it now.

https://github.com/JetSetIlly/Gopher2600/releases/tag/v0.40.0-preview
#5
General Discussion / CRT emulation
25 Dec 2024, 09:47 PM
I'm deep into thinking about CRT emulation at the moment so this caught my eye. This is a level of detail I'd not even considered.

https://blurbusters.com/crt-simulation-in-a-gpu-shader-looks-better-than-bfi/

I don't think it would have much benefit for 2600 emulation though. Still it's interesting to think about.
#7
Gopher 2600 / Improved Rewind
02 Dec 2024, 10:25 AM
I've made an improvement to the rewind system this evening. I was prompted by a problem somebody was having on AtariAge and I tried to solve it.  I think it's quite interesting so I'll give a brief explanation here.

The problem was related to being able add a breakpoint and being able to step back an instruction once the breakpoint has triggered. Gopher2600 can do this and has been able to for a long time, but user-input could cause issues. I'll explain why:

Gopher2600 creates a snapshot of the emulated machine every frame but crucially, can automatically reconstruct any intermediary state. So, from a paused position you can instruct the emulator to, for example, "GOTO frame 10, scanline 4, clock 50" and it can do that even though that specific state was never recorded.

I like to think of this as being a bit like video compression - record key-frames and delta information for the frames in between. In the case of the Atari 2600, the delta information is just the instructions of the 6507 program.

However, controller input from the user is also delta information that needs to be fed into the reconstruction. Gopher2600's flaw could be seen when rewinding to an intermediary state where user input happened after a key-frame. In those instances user-input would be lost. For rewinding gameplay, this wasn't a problem, but it can very definitely be a problem inside the debugger.

The improvement is to record user-input during the intermediary states and reinsert the user input on reconstruction.

The specific example I was trying to solve was to be able to step back an instruction after the emulation has halted due to a memory write. In this example, the memory write happens in response to user-input so previously, stepping back an instruction from the breakpoint would result in a different reconstructed codepath - causing the debugger to be in an unexpected place.

I created a short video demonstrating the new feature.


1) A "watch write" command is entered in the terminal
2) I press "right" on the keyboard (you can see the SWCHA register in the Ports window change briefly)
3) The emulation is halted and the reason given in the title bar
4) Execution can be stepped back to the previous instruction as expected


Gopher2600's input system is quite complex so I need to make sure all this is bug free and robust before making another release. But this is something I've been wanting to add for a long time. Happily, it turned out to be a lot easier than I expected :-)
#8
I've been working on NTSC colour generation for gopher2600. In other words, using the HUE-LUM nibbles used in the console's colour registers, create the YIQ signal.

Converting the HUE to the I and Q chroma values can be done by mapping the HUE value to a colour wheel:

   
phi = hue * 360 / (15 * adjust)   
The adjust is a value representing the colour adjustment potentiometer in the console.

We also need to adjust for the colour burst value.

   
phi += colourBurst
I and Q can then be derived:

   
I = Y * math.Cos(phi * degToRad)
Q = Y * math.Sin(phi * degToRad)
   
Y is the luminance value derived from the LUM nibble, the details of which aren't important here.

For display, the RGB values can then be extracted from the YIQ information.

So, the NTSC palette created without ever explicitely specifying the RGB values, which is what I want.



My question, is about how the PAL consoles work in this regard.

PAL encodes colour using YUV so I've started off in a similar way by mapping the HUE value to a colour wheel and then converting the phi value to U and V.

However, converting the YUV values to RGB values does not reproduce the expected PAL palette. I can get close but it's definitely not correct.

I think my mistake is in assuming that the HUE values correspond to equally spaced positions on the colour wheel.

So my question is this: do PAL consoles map the HUE values to UV values explicitly, rather than dividing a colour wheel like the NTSC consoles? Or is there a non-obvious way of performing the division?
#9
Gopher 2600 / v0.35.0
02 Oct 2024, 09:54 PM
I've put together a new release. Mainly bug fixes reported by Andrew Davie.

https://github.com/JetSetIlly/Gopher2600/releases/tag/v0.35.0

This release also contains small changes to the audio system, as discussed in this AtariAge thread https://forums.atariage.com/topic/370460-8-bit-digital-audio-from-2600/
#10
I don't know anything about this monitor, but an all-in-one solution (including RF input) sounds extremely useful. https://www.checkmate1500plus.com/

Video with the creator talking about it: https://www.youtube.com/watch?v=IWBVATSPPlw
#11
General Discussion / Janice
13 Aug 2024, 10:58 PM
There's an interesting topic brewing on AtariAge regarding the Janice variation of the TIA. Posting here in case anyone has any insight to add.

https://forums.atariage.com/topic/317039-pluscart-sd/?do=findComment&comment=5510832
#13
Programming / Optimising C Compilers
18 Jul 2024, 05:01 PM
While working on the CDFJ driver for the STM32 cartridges (UnoCart and PlusCart)
the question of optimisation has arisen. In particular how C is optimised during
compilation.

To illustrate the effect of written code on the instructions generated by the
compiler, I'll use the bank-switching logic for CDFJ.

The logic for bank-switching is a little unusual in that the bank-switching
addresses (hotspots) do not line up exactly with the bank that will be switched
to (CDFJ+ corrects this). For reference, here is the list of hotspot addresses
and corresponding banks

1ff4   6
1ff5   0
1ff6   1
1ff7   2
1ff8   3
1ff9   4
1ffa   5
1ffb   6


The first pass of driver development resulted in this. We'll call this code-A:

if (addr >= 0x1ff4 && addr <= 0x1ffb) {
   if (addr == 0x1ff4) {
      bankPtr = &cartridge[0x6000];
   } else {
      bankPtr = &cartridge[(addr - 0x1ff5) * 0x1000 ];
   }
}

On the surface it looks concise and as best as I can tell the logic is correct.
But, and this important, it's not /easy/ to tell if it's correct just by
looking. It requires a little bit more thinking than I would like as a
maintainer of the code.


The second pass of development changed the bank-switching code to this. We'll
call this code-B:

switch (addr) {
   case 0x1ff4:
      bankPtr = cartridge + 0x6000;
      break;
   case 0x1ff5:
      bankPtr = cartridge + 0x0000;
      break;
   case 0x1ff6:
      bankPtr = cartridge + 0x1000;
      break;
   case 0x1ff7:
      bankPtr = cartridge + 0x2000;
      break;
   case 0x1ff8:
      bankPtr = cartridge + 0x3000;
      break;
   case 0x1ff9:
      bankPtr = cartridge + 0x4000;
      break;
   case 0x1ffa:
      bankPtr = cartridge + 0x5000;
      break;
   case 0x1ffb:
      bankPtr = cartridge + 0x6000;
      break;
}

What do you think? Better or worse.

Well, it takes more room on the screen but I would hope we can agree that the
/intention/ of the code is clearer. A little bit of commentary explaining and
reinforcing that intention and I would be happy with that as the final code.


But what about the execution efficiency? This is a time-critical application so
the code needs to be efficient.

To understand this we can use the objdump tool. This tool allows us to view the
instructions generated by the compiler along with the line of source code that
produced the instructions. (In the extracts below, the results are sorted by line
number.


These are the results for code-A:

cartridge_emulation_ACEROM.c:104
         if (addr >= 0x1ff4 && addr <= 0x1ffb) {
 802819a:   f5a1 50ff    sub.w   r0, r1, #8160   @ 0x1fe0
 802819e:   3814         subs   r0, #20
 80281a0:   b280         uxth   r0, r0
 80281a2:   2807         cmp   r0, #7
 80281a4:   d854         bhi.n   8028250 <emulate_ACEROM_cartridge+0x150>
cartridge_emulation_ACEROM.c:105
            if (addr == 0x1ff4) {
 80281a6:   f641 70f4    movw   r0, #8180   @ 0x1ff4
 80281aa:   4281         cmp   r1, r0
 80281ac:   f000 8090    beq.w   80282d0 <emulate_ACEROM_cartridge+0x1d0>
cartridge_emulation_ACEROM.c:106
               bankPtr = &cartridge[0x6000];
 80282d0:   4e1e         ldr   r6, [pc, #120]   @ (802834c <emulate_ACEROM_cartridge+0x24c>)
 80282d2:   e778         b.n   80281c6 <emulate_ACEROM_cartridge+0xc6>
cartridge_emulation_ACEROM.c:108
               bankPtr = &cartridge[(addr - 0x1ff5) * 0x1000 ];
 80281b0:   031e         lsls   r6, r3, #12
 80281b2:   f106 56f0    add.w   r6, r6, #503316480   @ 0x1e000000
 80281b6:   f506 4640    add.w   r6, r6, #49152   @ 0xc000
 
 
 It doesn't look too bad but we won't really know until we compare it to the
 instructions generated by code-B:

cartridge_emulation_ACEROM.c:124
            switch (addr) {
 802817a:   f5a3 51ff    sub.w   r1, r3, #8160   @ 0x1fe0
 802817e:   3914         subs   r1, #20
 8028180:   2907         cmp   r1, #7
 8028182:   d803         bhi.n   802818c <emulate_ACEROM_cartridge+0x8c>
 8028184:   4e89         ldr   r6, [pc, #548]   @ (80283ac <emulate_ACEROM_cartridge+0x2ac>)
 8028186:   447e         add   r6, pc
 8028188:   f856 9021    ldr.w   r9, [r6, r1, lsl #2]
 
 
 That's it! The entire switch statement from code-B has been collapsed into 7
 instructions. Compare that to the 13 instructions from code-A. In terms of
 bytes, that's 18 bytes versus 36 bytes.
 
 (Both sets of instructions also load data from outside the instruction
 block so strictly speaking the amount of space required is a little greater for
 both examples)
 
 In terms of cycles, it's difficult to say without actually executing the code
 but looking at the negative path (ie. when the address is not one of the
 hotspot addresses): for code-A it takes 5 instructions to get reach the exit
 branch, while it takes only 4 instructions for code-B.
 
 That's a rough estimate but the switch statement certainly isn't any slower.
 
 So not only is code-B easier to read and therefore maintain, it produces
 smaller and faster code.
 
 
 The first lesson here is not to "optimise" without profiling the execution. Or,
 as we've done here, inspecting the generated code. For small sections of code,
 inspection is fine but for larger sections of code, such as the game logic in
 your custom section, profiling is the only practical option.
 
 But the most important lesson is that optimising C compilers are better than
 you might think. Write clear code and the C compiler will do well. I always
 appreciate being reminded of that and I hope you do too :-)
#14
Gopher 2600 / v0.33.0
07 Jul 2024, 07:45 AM
https://github.com/JetSetIlly/Gopher2600/releases/tag/v0.33.0

Highlights in this release are a reduction in the amount of memory consumed by ELF. High memory is a direct consequence of the rewind system and because ELF can potentially target a large array of memory. The fix is (a) to only take copies of memory sections that are volatile and (b) to compress those sections that might have changed.

Solution (b) takes advantage of the fact that huge swathes of memory will remain untouched and thus contain large runs of zero bytes. A simple RLE is both quick and effective here.

I'm sure this can be improved further but I'm happy with this for the time being.


The other significant change is the ability of the television to break into the debugger automatically under certain circumstances. For example, if the VBLANK or VSYNC profile changes, it is useful for the developer to know immediately. Care has been taken for these breakpoints not to trigger during the startup phase of a ROM.

The controls for these breakpoints are in the Preferences window.

Screenshot from 2024-07-06 22-43-09.png

As a complement to this I've also added VBLANK and VSYNC information to the "FPS" overlay for immediate feedback

Screenshot from 2024-07-06 22-35-53.png

The debugger will now show the break condition in the menu bar. . With a number of automated breakpoints now available, including the television VSYNC/VBLANK breakpoints described above, this is helpful to ascertain why the emulation has entered the debugger. By way of example, the screenshot below shows a break caused by an absent VSYNC signal.

Screenshot from 2024-07-06 22-40-59.png
#16
Al_Nafuur, MarcoJ and myself have been working on getting DPC+ working on UnoCart and PlusCart. It's been half-working for several years but the half that didn't work, the interesting part, was execution of ARM custom code.

I'm pleased to say we succeeded. Here's Marco and Wolfgang on ZeroPageHomebrew making the announcement https://www.youtube.com/watch?v=BdGMwXG-rks

The reason DPC+ games didn't work on the Uno/PlusCart was because the memory layout of these cartridges is significantly different than the Harmony. So for a DPC+ ROM to work it needs to be either (a) recompiled or (b) poked.

Marco and I started by poking the Scramble demo. We got most of the way there but the game wasn't running quite right. Graphical glitches were everywhere. We weren't sure if we'd poked everything we needed to or if the DPC+ driver itself wasn't quite right so we needed a different approach.

John Champeau very graciously gave me access to the source code for Scramble and I rebuilt the game with the UnoCart addressing. To cut a long story short we eventually got Scramble running on the PlusCart.

The vast bulk of DPC+ games are written in Batari Basic (I'm genuinely surprised there are so many) so getting these working was a big part of the project. Happily, Al_Nafuur realised very early on that all we needed to do for these ROMs was to slice out the bB DPC+ kernel section and replace it with our own. Again, to cut the long story short, we got this working too! Dozens of DPC+ games are now working on the UnoCart and PlusCart

The tool for converting bB DPC+ ROMs has just been released. Binaries are available for common platforms. https://github.com/JetSetIlly/relocateBB/ Hopefully, this will become part of the standard bB build process.

One awesome detail I should mention is that the PlusCart automatically converts bB DPC+ ROMs as part of the process of downloading from the network.  How convenient is that?! So for developers, they can now use the PlusCart for bB development just as easily as they can the Harmony, if not more easily.

#17
https://forums.atariage.com/topic/344323-fluid-simulation-for-new-2600-game-concept/?do=findComment&comment=5489943

Mattress Monkeys is the first public release of a game that uses the new ELF format. This new 2600 format facilitates the relocation of ARM code in accordance with the specific memory requirements of the host cartridge.

The problem with DPC+ and CDFJ is that they are specific to a particular cartridge type. In practical terms this means that game binaries are specific to either the Harmony or the Uno/PlusCart. ELF solves that problem by rewriting address references in the ARM program as part of the loading process.

The goal here is for ARM games to be usable on a variety of cartridge types with different memory requirements. Whether that be UnoCart, PlusCart or other cheaper alternatives that have yet to be developed. I hope that the Harmony class of cartridges will be updated to support ELF too, but that remains to be seen.



Mattress Monkeys also uses something called StrongARM. StrongARM can be thought of as a suite of functions that can be called from the ARM program. Each function causes the cartridge to stuff the data bus with 6507 instructions. In other words, Mattress Monkeys is a complete bus-stuffing game. There is no bank-switching as such, just an ever continuous and ever changing stream of instructions.


So, memory relocation and practical bus-stuffing. Two big milestones in 2600/ARM game development. Both technical achievements should be credited to ZackAttack and I think is something to be celebrated :-)
#18
Gopher 2600 / v0.32.0
12 Jun 2024, 05:26 AM
https://github.com/JetSetIlly/Gopher2600/releases/tag/v0.32.0

* The main changes are to the way the TV signal is handled, in particular to the the way the VSYNC signal is handled.

Previously, the effect of bad VSYNC was offloaded to the pixel renderer.  At some point I decided that this was wrong and moved it into the OpenGL shader, which was an even worse decision. I've finally realised that the best place to introduce the screen-rolling effect is inside the television itself. In other words, screen-rolling no longer just a simulated graphical effect.

This has consequences with regard to how we count frames in the debugger, but it's really only an issue for those ROMs that aren't behaving correctly in the first place.

* The second change with regard to the television is that the screen now keeps to a strict 4:3 aspect ratio. The generated TV image is always squeezed into that aperture.

Previously, a TV image that required additional space at the top and bottom of the normal dimensions, would cause the screen to increase in size. This obviously isn't correct and resulted in the screen being something other than 4:3 in ratio.

* The final important change is to the OpenGL shaders. Because of how I was chaining the shaders, particularly in the CRT chain, there were small but noticeable artefacts in the image. These have been removed now and the image should be a lot "cleaner".


In addition, there are bug fixes to the ARM emulation. In the recent past, when adding support for the STM32, I changed the way memory latency was calculated. This caused an error in the accuracy of cycle counting. As ever, bugs in the ARM emulation are tracked down with the help of Andrew Davie.


The release page has the full list of changes.
#19
An unexpected side effect of the 2600+ is the discovery of ancient bank switching schemes.

Examples have been found of Smurf Rescue and Zaxxon that feature a hitherto unknown switching scheme, which we now call wF8.

Discussion on AtariAge: https://forums.atariage.com/topic/367157-smurf-rescue-alternative-rom-with-wf8-bankswitch-format/

The 2600+ is a key ingredient here because until recently, cartridge dumping was a fringe activity. But the 2600+ is based on cartridge dumping so more people are doing it and with a wider array of cartridges.

I wonder if there's anything else out there?
#20
Gopher 2600 / v0.31.0
06 May 2024, 02:42 AM
https://github.com/JetSetIlly/Gopher2600/releases/tag/v0.31.0

This version introduces TV colour controls. Nothing too fancy but the results are good I think.

v0.30.0 broke the ROM Selector for Windows users so hopefully, that's fixed.


Most importantly, is a bug fix regarded new installations. At some point in the past, I made the "Frame Queue" something that could be altered through the preferences. Unfortunately, the default value was zero, which is likely to cause the display to be very choppy.

I haven't noticed it before because my preferences are set nicely, but the defaults for new users were definitely not correct. I've likely created a sour impression of the emulator for many people, because of this 😞

If you've been disappointed in Gopher2600 in the past, then this version may very well improve your experience.