What's new

Game Boy

mendus

New member
A question about palettes int DMG mode. Which ones does it use? There should be a {WHITE, LIGHT GREY, DARK GREY, BLACK} for backgrounds, but what are the 2 palettes for objects?

And what EXACTLY do the registers BGP, OBP0, OBP1 store and in which adress are they?

Thanks in advance.
 

Shonumi

EmuTalk Member
[MENTION=111217]venge[/MENTION] Yes, I had a look at Prehistorik Man's code in BGB a while ago. If I recall correctly, it would change the BGP register every STAT interrupt (based on LY == LYC, incrementing LY each time). It would change the BGP to all black or something, but for a set amount of cycles, then switch it back to the value it had previously. Used carefully, this technique essentially "prints" the large characters that bounce up and down in the intro.

The GB's VRAM access timings are around somewhere online, I think I saw it here: http://blog.kevtris.org/blogfiles/Nitty Gritty Gameboy VRAM Timing.txt It's not particularly hard to emulate this type of behavior if your emulator runs each component (MMU, LCD, CPU, APU) on a cycle-by-cycle basis, as each cycle actually occurs. The thing is, my emulator (and others I assume) aren't cycle accurate or even try to run things on a cycle-by-cycle basis. Instead, I tend to run the current GB instruction or interrupt, see how many cycles have run in that time period, then determine what actions each emulated component needs to take. If a large amount of cycles (8 is enough even :p) passes, that would mess with the pointer when it comes time for the LCD to decide. Even performing something LD A, HL or LD HL, A would cause problems (say when it's time to change the BGP), my emulated LCD will see that 8 cycles have passed, but has no knowledge of what instruction was previously run or how that plays into memory accesses; it's possible that when it reads the BGP data when generating a pixel, it would miss. Let me elaborate:

Assuming I'm performing LD HL, A and HL points to BGP ->

On a real GB:
(1st 4 cycles) -> CPU reads value of A, LCD is in the process of looking up the tile data (this takes 6 cycles total, gets the data in 2, but does it three times altogether)
(2nd 4 cycles) -> CPU writes A at HL, LCD finished the lookup process (and the pointer is updated) by the 2nd cycle here, but the CPU has not finished writing to HL by then, thus the LCD should still use the "old" BGP value when drawing the this tile.

On my emu:
(8 cycles, done all at once) -> CPU reads A, inserts that at HL, LCD could see that the pointer has updated (8 > 6), but even if it could, it would incorrectly read the "new" BGP value no matter what.

Performing things on a cycle-by-cycle basis would eliminate the issue for me, but that's a lot of reworking for one game, thus it's on the back-burner for me, especially when other more "exciting" things are waiting to be implemented :D

[MENTION=106194]mendus[/MENTION] - The Background Palettes on the DMG are the same colors as the sprites (or objects if you prefer). The thing is, the first color in the Object Palette (color 0) is transparent, as if the LCD simply does not draw it. The BGP, OBP0, and OBP1 registers are at the memory locations 0xFF47, 0xFF48, and 0xFF49 respectively.
 
Last edited:

mendus

New member
[MENTION=110864]Shonumi[/MENTION] Are there 3 equal palettes? That doesn't make much sense to me, unless the colors are switched. Did you mean that color 1, for example, is light grey in all 3 palettes?
 

Shonumi

EmuTalk Member
[MENTION=106194]mendus[/MENTION] If by "equal" you mean "they all use the same colors" then yes. The Background Palette has access to four shades, as do the two Object Palettes. It helps to think of the four shades in terms of a pixel being "ON" or "OFF" that is to say, imagine Black being 100% ON, Dark Gray 66% ON, Light Gray 33% ON, and White obviously being 0% ON, or OFF.

Are you confused as to how the palettes work? Take BGP for example. It's an 8-bit MMIO (Memory-Mapped Input/Output) register. The GB reads the 1st two bits; the value of these two bits determines what shade to use for Color 0. It reads the next two bits, which determines the shade for Color 1, so on and so forth.

Let's pretend BGP is 0xE4 in hexadecimal (0b11100100 in binary), bits are read right-to-left:

Color 0 -> Bits 0-1 are 00, the value we get is 0. Every time we want to draw something that uses Color 0, we "lookup" what 0 is supposed to represent. It represents White
Color 1 -> Bits 2-3 are 01, the value we get is 1. Every time we want to draw something that uses Color 1, we "lookup" what 1 is supposed to represent. It represents Light Gray
Color 2 -> Bits 4-5 are 10, the value we get is 2. Every time we want to draw something that uses Color 2, we "lookup" what 2 is supposed to represent. It represents Dark Gray
Color 3 -> Bits 6-7 are 11, the value we get is 3. Every time we want to draw something that uses Color 3, we "lookup" what 3 is supposed to represent. It represents Black

See here for more info: http://gbdev.gg8.se/wiki/articles/Video_Display#LCD_Monochrome_Palettes

It's the same principle for the OBPs. Note that this example shows a simple palette (Color 0 is White, Color 1 is Light Gray, Color 2 is Dark Gray, Color 3 is Black), but you could have something like this:

Let's pretend BGP is 0x3D in hexadecimal (0b00111101 in binary)

Color 0 -> Bits 0-1 are 01, the value we get is 1. Every time we want to draw something that uses Color 0, we "lookup" what 1 is supposed to represent. It represents Light Gray
Color 1 -> Bits 2-3 are 11, the value we get is 2. Every time we want to draw something that uses Color 1, we "lookup" what 2 is supposed to represent. It represents Black
Color 2 -> Bits 4-5 are 11, the value we get is 2. Every time we want to draw something that uses Color 2, we "lookup" what 2 is supposed to represent. It represents Black
Color 3 -> Bits 6-7 are 00, the value we get is 0. Every time we want to draw something that uses Color 3, we "lookup" what 0 is supposed to represent. It represents White
 
Last edited:

mendus

New member
[MENTION=110864]Shonumi[/MENTION] Ah alright. I don't know why I thought it had 3 fixed palettes and I was not considering the program might want to modify them, which was confusing me. Thanks for clearing it and also for the link, I was unaware of that wiki.
 

venge

New member
[MENTION=111217]venge[/MENTION]
Performing things on a cycle-by-cycle basis would eliminate the issue for me, but that's a lot of reworking for one game, thus it's on the back-burner for me, especially when other more "exciting" things are waiting to be implemented :D

Very true, but see how easy it is in pseudo-code to get the first result:
int lcd_pointer = 0;
switch(mode)
{
...
...
...
case 3:
for(; lcd_pointer < CPU.clock + lcd_pointer_prev ; lcd_pointer++){
if(lcd_pointer < 160)
UpdatePixels(lcd_pointer);
}
lcd_pointer_prev = lcd_pointer
... <your mode 3 timing logic goes here where you also set lcd_pointer = 0>
break;
...
...
...
}
If you look carefuly you DO things on cycle basis in your emulator. Since you have a working cycle based timing in your PPU there's a place for you to add that code. But 99.999% of titles work nicely using a simple internal pointer at the end of mode 3, and it's faster too, because of your compiler's optimization.

So the result is pretty clear. DURING a correctly timed VRAM scan this code is enough to show you the prehistorik man intro screen correctly. I would also add, this is a pretty sick (as it is smart) way to paint on GB screen, but hardware can't judge its programmers.

Take a look: s7.postimg.org/xpic0ymi3/xnaprehistorik.png (copy paste, I still don't have enough posts to include a link)
 
Last edited:

Shonumi

EmuTalk Member
If you look carefuly you DO things on cycle basis in your emulator.

Correct, I do things on a cycle basis, but not cycle-by-cycle (the LCD can in some cases, but the APU doesn't at all, and while this works well enough, that's a different matter of issues I've encountered). This is basically how GBE operates

Code:
Instruction or interrupt is executed -> cpu.step();
Program stores amount of cycles passed -> cycles_passed = xyz;
Emulated LCD performs actions based on how many cycles have passed -> lcd.step(cycles_passed);

What you're describing with the pointer is what I mentioned earlier, per-pixel rendering, rendering each pixel after a given amount of cycles. However, because of the way GBE operates, there is not an "easy" way to make something that is completely hardware accurate without changing parts of the CPU, MMU, and LCD. It can be done, but it's not something that'd fit nicely into a single git commit; it's something I'd likely have to make a branch for. A "shortcut" method could be made accurate enough to play Prehistorik Man without glitches (psuedo-code below) to reach a "good enough" level of playability. But getting it accurate like a real DMG GB needs closer attention. It's not just the matter of getting Prehistorik Man running fine; some demos manipulate things midscanline as well, and though they're not commercial games, it irks me if GBE can't do the same as my old Game Boy Pocket or BGB can.

Anyway, perhaps I wasn't entirely clear about why it's hard to do things on a cycle-by-cycle basis for my emulator (I won't speak for others ;)). GBE processes things in as many cycles an interrupt or instruction took; it doesn't breakdown what happens in between each of those cycles (like 12 cycle operations like LD HL, nn). It's easy enough to tell the emulated LCD "hey, every 6 cycles, we will fetch and render 8 pixels from Tile X" when you are doing things on a cycle-by-cycle basis, that is to say the emulated CPU tells the emulated LCD 4 cycles have passed and it has to do work, but anything greater than 8 cycles introduces the potential chance for inaccurate hardware emulation. Going back to simply changing the BGP midscanline, if GBE were to try to emulate the LCD by generating pixel data every 6 cycles, it would look something like this (assume some_tile_number points to the current tile getting fetched from the Tile Map):

Code:
//During VRAM read mode, fetch and generate pixel data
if((lcd_incoming_cycles + lcd_current_cycles) >= 6)
{
    lcd_current_cycles += lcd_incoming_cycles;
    
    //If a large amount of cycles have passed (*cough*Interrupts*cough*), determine how many tiles were fetched in that time
    //Integer division rules
    u8 tiles_fetched = lcd_current_cycles / 6;

    //Fetch and generate the tiles pixels for however many tiles we need
    while(tiles_fetched-- > 0)
    {
        update_scanline_data(some_tile_number++);
    }

    //Make sure lcd_current_cycles contains any leftover cycles 
    //Example when 2 4-cycle ops are run, 8 cycles have passed, 8 - 6 = 2, tile fetching process begins again after another 4 cycles
    lcd_current_cycles = (lcd_current_cycles % 6);
}

Again, something like that would probably work for Prehistorik Man, but as I said, it can fail whenever the emulated CPU tells the emulated LCD 8 or more cycles have passed. Say I use LDH n, A since it's a relatively easy way to write to many of the MMIO regs. That takes 12 cycles to execute, meaning 2 tiles could be fetched during Mode 3. In the 1st 4 cycles, the value at the PC (on a real DMG) is read by the CPU -> 2nd 4 cycles it calculates the address to write -> 3rd 4 cycles it actually writes A to 0xFFnn. If BGP is being changed, GBE still won't catch it depending on the cycles. Let's assume lcd_current_cycles is 0

Code:
//During VRAM read mode, fetch and generate pixel data
Is 0 + 12 > 6? Yup, continue
{
    lcd_current_cycles += 12; //Now it's 12
    
    //If a large amount of cycles have passed (*cough*Interrupts*cough*), determine how many tiles were fetched in that time
    //Integer division rules
    u8 tiles_fetched = 12 / 6; //We need to fetch data for 2 tiles, now! 

    //Fetch and generate the tiles pixels for however many tiles we need
    while(tiles_fetched-- > 0)
    {
        update_scanline_data(some_tile_number++); //Woah, woah wait! The emulated CPU has already changed the value of BGP!!
        //The emulated CPU runs the instruction first (all at once), then tells the emulated LCD the number of cycles
        //Both tiles need to have the "old" value of BGP, because technically the write [i]is not completed[/i] until the 12th cycle
        //But the CPU has long since overwritten that value...   :|
    }

    ....
}

So, for me to do this accurately, it requires coordination between the CPU, LCD, and MMU. Every time 4 cycles are passed (1 machine cycle), the CPU and LCD should run through their step() functions. Waiting beyond that could lead to results that aren't true to the hardware.
 
Last edited:

venge

New member
Yes I get your point. Actually we don't disagree in any point. I understand that a large cycle instruction like a PUSH could mean 2-3 vram accesses DURING its execution while a very small, like HALT, could mean that lcd didn't have the time to fetch anything and it's waiting. But since we emulate a HLE display, workarounds are acceptable. A very accurate lcd display emulation (as described in lcd timing manual) would truly need a radical rewriting of all the components of conventional emulators (as you mentioned again).
 
Last edited:

Rüdiger

New member
Wow, it's really lively here. :bounce:

A relatively straightforward solution to get cycle-exact timing (at least on my emulator) could be
storing the offset of the actual memory access from the beginning of the instruction in a table
and passing the correct time to the register read/write-callback.
Instructions that involve more than one memory access would require a bit more work, but nothing too serious.

There are only a handful of registers that require exact timing (GPU, timers, APU?), so the overhead should be small.
A variation of this would be collecting the (time,register,value) tuples and then processing them all at once (each scanline for the LCD or in the buffer callback for the APU).
This variant of course only works for registers that are not changed by the hardware.

Could this work or am I missing something?

On a different note, the SGB support is "complete enough" for my purposes and I merged everything back together.
So far, it's working :satisfied .
 

Shonumi

EmuTalk Member
[MENTION=111217]venge[/MENTION] - Yeah I wasn't disagreeing, just trying to explain the situation with my emulator. Everyone builds them differently :D Technically, what I described would only be an issue during write operations, and even then, only to MMIO registers like the palettes. It's really not so radical when you get down to it, you just have to have each component execute for only 1 machine cycle (4 CPU clocks) and this is how Gambatte is set up, so that project is a good example if you're interested (BGB most likely does too, but it's not open source). The hardest part is restructuring the MMU components. Something as simply as loading an immediate into HL (LD HL, nn) would have to be broken down into three stages.

IMO, I would really have liked to have built my emulator from the ground-up to operate cycle-by-cycle for every component. When I first started out (a noob to emu programming) I was following Imran Nazar's GB emu tutorials, and a lot of my design still functions around some of his design choices. It's just easier dealing with accurate behavior from the start, though so far the Game Boy hasn't proven overly picky about somethings. Demos are a different story :p

[MENTION=106985]Rüdiger[/MENTION] - Both methods sound like they should work, my brain is a bit fuzzy after just waking up, so I haven't had time to really think it through, but something like that would work for accurate APU emulation. In fact, since the APU is very predictable, you can run a large amount of cycles all at once (HLE like venge said) but as long as the buffer reflects changes as they have happened, the output should be fine. The same could apply to the LCD in theory (well, not too many cycles should pass ;))

Glad to see you merged SGB support. You know there's probably a way to get multiplayer functionality up and running, I don't think VBAM does that (higan maybe?). Would be interesting to see someone else try it.

As a side note, I'm digging into GBA emulation now (mostly emulating the ARM CPU). Not a whole lot implemented. Maybe I'll start a GBA thread once I start going somewhere. Thankfully the GBA is very documented.
 
Last edited:

venge

New member
[MENTION=110864]Shonumi[/MENTION] It seems Imran Nazar inspired many people into emulation due to his tutorials (I'd like to thank him if he ever visits this forum as he inspired me too). It's true, game boy isn't that grumpy with details. In fact after 7 days of coding, 8/11 instructions failed, worse LCD timings couldn't happen, and tetris showed me the moscow palace. I was happy. Really.
I want to update my post to point out a mistake I've made. The reason this code worked at the end of OAM was the fact the emulator was drawing before the interrupt additional clocks. Also, CB opcode as well as EI were unclocked making display out of sync. Sorry if anyone got misinformed by it. I also updated the code.
  Spoiler:
Concerning the dynamic scanlines we talked, using the nice doc you linked, I came up with the idea to start drawing 6 pixels + the rest of my clock from OAM (-80 clocks) at the END of OAM. With this dirty HLE code I could eventually avoid the lens effect (of the already changed pallete in mode 3) at the left side of prehistorik man's intro screen and display it perfectly (compared to VBAM and BGB). (Actual code from XNA boy)

Code:
case 2:

if (clock >= 80) {
	set_MODE_during(3);
	clock -= 80;
	
}
break;

case 3:
int x_clock = clock - 8;
for (; lcd_pointer < x_clock; lcd_pointer++) {
	if (lcd_pointer < 160) {
		UpdatePixel(lcd_pointer);
	}
}

if (clock >= 172) {
	if (check_stat_3()) {
		Memory.mem[Def.IF] |= 2; //interrupt.
	}
	set_MODE_during(0); //<--- Enters H-BLANK
	clock -= 172;
	lcd_pointer = 0;

}

break;
That extra offset is not needed anymore.
  Spoiler:
int rest_pix = 6 + clock; saved the day for me.
And as I told you the other day, since we have a HLE emulation for the display, that is enough for me I believe. Now, I don't know if other games or demos use dynamic X to draw but, as you said, demos are a different story :) . If I ever have more passion to deal with the CPU once again, I'll certainly remake it into cycle by cycle.
Shonumi. I wish you luck and clear mind for the Game Boy Advance implementation. Don't forget to inform us for a new thread (actually I haven't even checked yet if you started it already ^^)
 
Last edited:

fleroviux

Member
As a side note, I'm digging into GBA emulation now (mostly emulating the ARM CPU). Not a whole lot implemented. Maybe I'll start a GBA thread once I start going somewhere. Thankfully the GBA is very documented.

I'm thinking about that two. I already got some experience with the Gameboy Advance hardware because I'm a romhacker. Let's see if I'm able to write a gameboy advance emulator. For my Gameboy Classic emulator I was recently working on sound emulation. But currently it lacks pleasure to work on that project ^^
 

Rüdiger

New member
I'm thinking about that two. I already got some experience with the Gameboy Advance hardware because I'm a romhacker. Let's see if I'm able to write a gameboy advance emulator. For my Gameboy Classic emulator I was recently working on sound emulation. But currently it lacks pleasure to work on that project ^^
I looked into that some time ago. Most of the hardware is pretty similar to the GB, but I think that at the moment, I don't have enough time for the CPU. Maybe in the holidays...
It would certainly require some different approaches than my current CPU core. :naughty:

I tried porting my emulator to emscripten. Getting it up and running took about 30 minutes, but then I spent several hours on persistent savegames and I can't get stable framerates or sound. :(
http://i.imgur.com/B1qLo59.png
 

venge

New member
Based on the HALT documentation in Pan docs, when interrupts are not enabled, in section 2.7.3 (Low Power mode), after HALT, the DMG cpu should repeat the next command for one time. Looking at the execution of Blargg's CPU instruction test 2 individual rom in BGB, it seems that the PC register is stalled, until a timer interrupt is on, even though interrupts are NOT enabled. Now comparing theory to practice, it seems there is a great difference from what I've understood reading pan docs. Am I missing something? I mean a step by step execution of the individual Blargg's rom should be like this?:
Code:
Starting from PC = 0xC363

$C363 | LD a, 05
$C365 | LD (FF07), a
$C367 | LD a, 0
$C369 | LD (FF05), a ; timer becomes zero 
$C36B | LD a, 0 ; (TIMA = 1)
$C36D | LD (FF0F), a ; IF is now zero.
$C36F | [B]HALT[/B] (TIMA = 1)
$C370 | NOP ; I've seen many things here. BGB stalls until timer overflows. A somewhat known open source emulator enables a timer interrupt flag at this point...
$C370 | NOP ; <--- Based on the docs shouldn't just this happen when IME isn't set? (TIMA = 3)
$C371 | LD a, (FF0F)
$C373 | AND a, 04 ; During those instructions could a timer interrupt flag be enabled?

What on earth a real DMG does in this situation?
 

RossIain

New member
Based on the HALT documentation in Pan docs, when interrupts are not enabled, in section 2.7.3 (Low Power mode), after HALT, the DMG cpu should repeat the next command for one time. Looking at the execution of Blargg's CPU instruction test 2 individual rom in BGB, it seems that the PC register is stalled, until a timer interrupt is on, even though interrupts are NOT enabled. Now comparing theory to practice, it seems there is a great difference from what I've understood reading pan docs. Am I missing something? I mean a step by step execution of the individual Blargg's rom should be like this?:
Code:
Starting from PC = 0xC363

$C363 | LD a, 05
$C365 | LD (FF07), a
$C367 | LD a, 0
$C369 | LD (FF05), a ; timer becomes zero 
$C36B | LD a, 0 ; (TIMA = 1)
$C36D | LD (FF0F), a ; IF is now zero.
$C36F | [B]HALT[/B] (TIMA = 1)
$C370 | NOP ; I've seen many things here. BGB stalls until timer overflows. A somewhat known open source emulator enables a timer interrupt flag at this point...
$C370 | NOP ; <--- Based on the docs shouldn't just this happen when IME isn't set? (TIMA = 3)
$C371 | LD a, (FF0F)
$C373 | AND a, 04 ; During those instructions could a timer interrupt flag be enabled?

What on earth a real DMG does in this situation?

From page 13 of "The internal workings of video game consoles: The GameBoy"
The HALT state is left when an enabled interrupt occurs, no matter if the
IME is enabled or not. However, if the IME is disabled the program counter register is
frozen for one incrementation process upon leaving the HALT state.

From page 22 of "GameBoy Programming Manual" :
Game Boy switches to HALT mode when a HALT instruction is executed.
The system clock and CPU operation halt in this mode. However, operation of source oscillation
circuitry between terminals CK1 and CK2 continues. Thus, the functions that do not require the
system clock (e.g,, DIV, SIO, timer, LCD controller, and sound circuit) continue to operate in this
mode.

Essentially the timer continues counting up even though the system is halted and the PC frozen. Once the timer overflows it will set bit 2 of the Interrupt Flag. Then when the interrupt is checked and since both the IE register and IF register have bit 2 set the HALT state will be left.
 

venge

New member
From page 14 of "The internal workings of video game consoles: The GameBoy"
Code:
; IME = Disabled
; Example code 1:
0x76 (HALT)
0x00 (NOP)
; Execution of code:
ReadOpcode(1) = 0x76 ; PC register is increased after every read
HALT ; Halt state entered
--Interrupt-- ; Halt state exited
ReadOpcode(2) = 0x00 ; Read new opcode, since IME is disabled PC register is frozen
; for one incrementation process making 0x00 being read twice
NOP ; Idle
ReadOpcode(2) = 0x00 ; Since the PC register is frozen, opcode 2 is read again

In my emulator, I have tested ALL game boy roms (including demos) and they execute fine (they do not crash), except Road Rash (test includes entering first level, and getting hit by an enemy when applicable). Test 2 from Blargg's test suite though, fails at HALT instruction. Page 13 and Page 14 from Ernberg's essay, actually justifies what Pan docs clearly mention before Martin Korth's examples (Pan docs, section 2.7.3 paragraph 2):
If interrupts are disabled (DI) then
halt doesn't suspend operation but it does cause
the program counter to stop counting for one
instruction on the GB,GBP, and SGB.
Marting Korth's examples on the other hand come to clarify everything mentioned before with some straighforward, in the face examples (Pan docs, section 2.7.3 EXAMPLES):
Code:
1) This code causes the 'a' register to be
incremented TWICE.
76 halt
3C inc a
. The examples are similar to those in Ernberg's abstract.
Game Boy switches to HALT mode when a HALT instruction is executed.
The system clock and CPU operation halt in this mode. However, operation of source oscillation
circuitry between terminals CK1 and CK2 continues. Thus, the functions that do not require the
system clock (e.g,, DIV, SIO, timer, LCD controller, and sound circuit) continue to operate in this
mode.
Obviously other operations continue to work, otherwise in case of CPU HALT, there would be no way to interrupt its HALT state and continue operation. In the example I mentioned in the post before, IME is not set and therefore PC register stops counting for one instruction (then continues incrementing is implied) and during those instructions (Blargg's individual cpu instruction test 2) there is NO WAY to generate a timer overflow interrupt assuming the TIMA timer is working correctly and HALT operation stops PC register for one instruction.
 
Last edited:

Shonumi

EmuTalk Member
[MENTION=106194]mendus[/MENTION] - I believe you mean opcode 0x18 not 0x17. 0x17 is RL A, not JR e.

Anyway, you convert the immediate from a signed value and then add or subtract it to the PC. The 8-bit immediate is in the format of 2's Complement. The math to do this (without relying on type-casting) is pretty easy to do:

Code:
//If Bit 7 is set, we have a negative number
if(immediate & 0x80)
{
    immediate--;
    immediate = ~immediate; //Bitwise NOT
    pc -= immediate;
}

//Bit 7 is not set, we have a positive number or zero
else { pc += immediate; }
 

mendus

New member
[MENTION=110864]Shonumi[/MENTION] yes, i meant 0x18.

That is the most logical translation, but I was confused with the -2 and that e ranges from -127 to 129 (2^8 + 1 numbers, so one must be ignored). Using the twos complement it should range from -128 to 127. Check the link I put.

- - - Updated - - -

In that case isn't it is enough to simply sum the lower byte of PC with the 8 bit immediate then, to obtain the result, using the 8 bit arithmetic overflow to your favor?

Edit: Nevermind, it does not give always the same result.
 
Last edited:

Top