15:59 2003-06-21
The Gekko opcode is a 4-byte word. Bits 0-5 is the primary opnum. There may be a secondary opnum in bits X-30, where X may vary from 21 to 26. Currently the only values of X are 21, 22, 25 and 26, but the OpArray code has support for all values from 6 to 30.

21:02 2003-07-24
GekkoUserManual error on stbx and eqv: 22 => 21. The B field is one bit too long.

14:54 2003-07-25
Floating-point intructions are likely not emulated exactly, especially with regard to the FPSCR and floating-point exceptions.

22:38 2003-07-31
All recompiled functions with two or more GPR/FPR operands can be optimized for the special cases Dest = Src1, Dest = Src2 and Src1 = Src2. Ex add, sub, or.

15:58 2003-08-04
Through assembly listing research, I have found that the this pointer is passed in ecx. This means that the cycle counter must be saved to memory before calling a class function.
10:30 2004-06-11
The cycle counter now resides in edi, but it must still be saved before calling a C/C++ function.

21:38 2003-08-12
Planned debugger features:
*Variable window size.
*List box with addresses & disassembly. Ex: 80003100	3C00CC00	addis r0, 0, 0xCC00
* *Press F9 to set/remove breakpoint at selected instruction. Red color somewhere to indicate breakpoint.
*Step(F8)/run(F5).
*Visual Studio-style memory window.
*Register boxes: one to select register (by writing), one to display value.
*Teh possibility to change memory/register value.(?)
*Saving settings/breakpoints/current register/memory window position.
14:12 2004-04-28
Check the dolwin debugger for more features.

22:52 2003-08-25
Implementation Note: In Gekko, the decrementer register is decremented and the
time base is incremented at a speed that is one-fourth the speed of the bus clock.

The bus clock is, what, almost 500 Mhz? But we don't count clock ticks, we count intruction cycles. The Gekko runs at ~1100 MIPS, so every fourth bus clock tick can be aproxximated by every second instruction cycle.
16:37 2003-08-27
From #gcdev @ Efnet:
[16:29:09] <tmbinc> does anybody knows the timebase clock for the gekko? should be ~40Mhz, but i'd like to have the exact value
[16:29:43] <Masken> like, how the TBL and TBU registers are updated?
[16:30:30] <Masken> one fourth of the bus clock, which is 485 MHz
[16:30:50] <Masken> so... 121.25 Mhz, then
[16:30:54] <tmbinc> hu
[16:30:54] <tmbinc> hm
[16:31:20] <tmbinc> i "hand calibrated" them and got some value around 40Mhz .. maybe i have to recheck my code :)
[16:31:38] <Masken> maybe
[16:31:43] <Masken> but I could be wrong
[16:31:53] <Masken> of perhaps the bus clock isn't 485 Mhz
[16:32:15] <Masken> yes...
[16:32:16] <Masken> "64-bit data bus 162 MHz clock"
[16:32:21] <tmbinc> ah ok :)
[16:32:35] <Masken> 162 / 4 = 40.5
[16:32:35] <tmbinc> 40.5 sounds reasonable then :)
[16:32:40] <Masken> :)
[16:32:42] <tmbinc> ok thanks :)
[16:32:46] <Masken> np

01:50 2003-10-01
HLE works like this: a defined bunch of PPC instructions is skipped and a CPU::function is called instead.

19:16 2003-10-11
Floating-point note: where not specified in the Gekko manual, assume ps0 will be used if HID2[PSE] = '1'.(?) Examples: fadds, fsubs.

15:46 2003-11-01
Added a timeout to pad and vsync operations. They should reset every 200 ms now.
10:57 2003-11-04
This may need to be changed when using the recompiler, which is much faster. Perhaps some sort of calculation based on the current MIPS rate.

23:33 2003-11-02
For the moment, most recompiled code will ignore HID2_PSE and behave like a regular PPC.
16:33 2004-04-30
The interpreter works like that, too.

10:56 2003-11-04
When optimizing recompiled code, I assume smaller code is faster code.
00:01 2003-11-07
When you must choose between a conditional jump or an unconditional jump (set XER_CA if EFLAGS_CR, for example), give the unconditional jump to the most likely path. <-- I'm not sure this is an optimization after all. Thought I'd write it down all the same.

01:35 2003-11-11
XER_CA operation in subtractions is most strange. Be ware.

21:27 2003-11-30
The EXI IMMDAT registers (base + 0x10) has a strange byte-order when transferring less than 4 bytes: The mask is 0xFF000000 for 1-byte and 0xFFFF0000 for two-byte transfers. I know this ain't very clear, but I hope it gets the message across.


18:13 2003-12-04
The BBA register space is rather memory-like; two byte reads from registers 0x16 and 0x17 seem to equal one half-word read from register 0x16.
00:12 2003-12-05
The BBA works like this: You make an EXI Imm write containing a read/write command and an address into the BBA memory/register space. The size of this space is unknown, but believed to be 0x1000 bytes. The first 0x100 bytes contain control and status data (a map will follow). Bytes 0x100-0xFFF is believed to be a Cyclic Read Buffer, used when recieving data from the network.
										|80
|Register	|Size(bytes)	|Description
|0x01		|1		|Revision ID. Value unknown, currently set to 0.
|0x20		|6		|MAC address. Probably hardcoded on a real BBA;
				|WhineCube uses the MAC address of the chosen
				|adapter.
|0x18		|2		|Read address into the Cyclic Read Buffer. If a
				|packet has been recieved, there'll be a 32-bit
				|header here. (0x100-0xFFF)
|0x16		|2		|Write address into the CBR. This is the next
				|byte that will be written to by the BBA. If
				|this equals the read address, there is no data
				|left to read.

If ([0x16] - [0x18]) == 1, the buffer is full. Trying to write to a full buffer *should* cause an exception but will currently invalidate all existing data.

Packets in the CRB are preceded by a 32-bit Descriptor:
0123456789ABCDEF0123456789ABCDEF
UUUUUUUULLLLUUUUHHHHHHHHUUUUUUUU

U is unknown information (set to 0 by WC). L is the now nibble of the 12-bit length, and H is its high byte.
After the descriptor follows HHHHHHHHLLLLb bytes of data, presumably an Ethernet packet.
15:25 2003-12-05
IP addresses are tricky business. WC can't very well use the computer's address, because then all the traffic to it will be copied to the WC BBA, ICMP, open TCP connections and all. However, people with a limited number of public addresses (like me) can't just add another IP address like that. People on private nets can do so; we may even let the GC use it's own IP address (you can add IP addresses to an adapter, if I'm not entirely mistaken).

My case is difficult...
We'll have to accept that the WC BBA won't have internet access unless we can give it an IP address on its own. However, it should still be possible to have local access using the GC's IP address. Because it's outside my LAN address space (and unallocated, to boot) the nearest switch or router will discard its packets. Example: WC BBA says its own IP address is 192.168.0.32 and tries to communicate with 192.168.0.100. WC will then add 192.168.0.32 to the physical adapter and translate 192.168.0.100 to 127.0.0.1... NO! that address is reserved for the GC speaking to itself. It'll have to be my public address (130.236.231.208). And back.

20:32 2003-12-07
This is how we'll do it:
Set the GC's initial IP address to 0.0.0.0.

Check ARP Requests for the GC's IP address. When it changes, issue an optional warning and degub-log it. Show it in the Status Bar. Allow all outgoing packets, but change destination IP addresses according to a 1:1 translation list (ex: 192.168.0.100->130.236.231.208).

Allow incoming ARP and IP packets with the GC's IP address as destination, as well as packets of indeterminable format (but issue a warning on and/or degub-log those).

I don't think there's any need to add the GC IP to the Windows adapter; the GC should send any ARP Respones it deems necessary.

23:45 2003-12-12
Weee, it works. Only at ~120 kBps with gamecubeserver 1.0.0.30, no firewall, hardcoded IP lock on 192.168.1.100->130.236.231.208, but it works. :)


03:38 2004-01-30
GP: As the load on the GP grows, it may be a good idea to give it it's own thread. It would then maintain its state and use a semaphor in conjunction with the WPAR interface, doing a Wait when it's out of data. If the GP thread is kept simple enough, it may not need any exit code; any allocated resources should be DELETED!! by the main thread and it can be terminated in mid-Wait.

05:02 2004-01-31
Of exceptions and ASSERTs: throw exceptions when input data we should have no control over is in error. Always ASSERT data we create ourselves, even if it is based on input data; if there's a risk of error in the input data, it should be checked with an exception when appropriate.

15:43 2004-01-31
GP: The indexed vertex data modes in the GP has become troublesome. The only current way of doing it is checking the index mode every time; way too cumbersome. Therefore I now implement direct memory pointer access. Use it only most carefully.

20:39 2004-02-07
[20:58:07] <Steve_-> DeskGone: you had the mod player by Costis, right? how does he manage the soundbuffer? circular?
[20:58:42] <DeskGone> He uses interrupts, so I guess he just fills the buffer when it's empty

03:07 2004-02-11
To differentiate from C++ exceptions, Gekko exceptions are named Interrupts in WhineCube.

02:47 2004-02-22
02[00:59:46] <Costisd> Groep, this is what my player on GC does ATM:
02[00:59:46] <Costisd> 	StopSample ();
02[00:59:46] <Costisd> 	LoadSample ((u32)0x80600000 + CBuf * 2048*4, 2048);
02[00:59:51] <Costisd> 	StartSample ();
02[00:59:53] <Costisd> 	CBuf ^= 1;
02[01:00:34] <groepaz>       LoadSample((u32)&stream_l[frame][0],((MIXLEN*AFM_MIXCHANS*AFM_MIXBYTES)));
02[01:00:34] <groepaz>        StartSample();

15:35 2004-03-14
Memory address translation goes like this, I think:
*If MSR[IR]=0 or MSR[DR]=0, whichever is appropriate, then there's no translation. Real Mode.
*Otherwise, the address is checked against the BATs. More than one hit is invalid and results in Big Phat Errors.
*If there's no BAT hit, the segment register specified by the top 4 bits of the EA is used.
*If the segment is direct-store, an ISI/DSI exception is generated.
*If not, a virtual address is generated and then looked up in the page table.
It's gonna be very slow. :/
16:38 2004-03-14
For now, only emulate BATs. Throw a lazer_exception or a rec_fatal_error on BAT misses.
01:57 2004-03-18
It seems the WIMG bits can be safely ignored, except for validity checking.
16:35 2004-03-19
There is no cache support in the current BAT implementation. Be Ware.
17:06 2004-03-19
Full BAT support will require a real BAT dump for initialization. I hope this rudimentary version will work, though.
17:16 2004-03-27
BAT and cache support are now mutually exclusive.

17:16 2004-03-27
The ICBI instruction invalidates an instruction cache block in which the EA(rA|0 + rB) is found. In the recompiler context, this means that the DynaRecBlock containing the EA (if any) should be deleted and its memory freed. Later, when an instruction in the block is to be executed, the DynaRec will re-recompile it, so to speak. :)

15:41 2004-03-29
I have noted that gc-linux ecexutes code at several different effective address spaces that map to the same physical address space. It would save considerable memory and recompilation time if the recompiler were to accept only physical addresses. However, it may break stuff. Research and consider.
21:11 2004-03-31
GC-linux overwrites lowmem instructions without icbi. The assumption that this only occurs in low memory may not be valid, but icbi-ing every memory write would be far too costly. Also, only the physical address is icbi'd. Since the system was designed for interrupts, that's not really a problem, but with recompilation address space physicalization (:]) it wouldn't be an issue.
22:46 2004-03-31
Fix the current Rec troubles with gc-linux, run a thorough check on the other demos and make a zip before changing even more.
19:03 2004-04-04
Troubles fixed. Now we can go back to work.
02:07 2004-05-02
Complete ICBI function only enabled with mem_translation.

13:25 2004-04-04
add_setcr0() trashes eax. There are errors. Be Ware.
13:29 2004-04-04
Errors searched and fixed.
18:08 2004-04-04
More cr0 errors discovered and fixed (I think). Be *very* careful to make sure SF and CF are properly set.

22:23 2004-04-16
All base classes must have virtual destructors. If not, they may not be destroyed correctly.

15:48 2004-04-30
Thread Execution Model:
* When recompilation starts, one screen refresh will be issued, then the timer will be stopped. When recompilation is complete, the timer will be resumed.
* First, the ini file and command line is processed. Then the window will be created. Then Direct3D will be initialized. Then the main loop will commence.
* If there's an error in loading or execution, WhineCube will shut down only if it was loaded from the command line. Otherwise, it will just display the error, not even close the CoreBase ('tis to allow for memory dumps, screenshots and (in the future) disassembly).
* When WM_CLOSE is recieved, we'll send the stop signal and wait for the emulation thread to finish before proceeding.
* When pausing during recompilation, use SuspendThread... that'll cause too much trouble. Allow pausing during recompilation,   but wait until it's complete before it takes effect in the thread... that's also weirding out...
  Add new signal: pause. no... any sort of pausing during recompilation will fuck up Timing...
  I know! Grey out Pause during recompilation!
01:51 2004-05-02
Details:
* When the Thread exits, a message will be sent.
* CreateTread must not be used for threads that use C standard library functions (ie. the defrag thread). Use _beginthread instead.
* * Oh yeah? Seems maybe only ExitThread is dangerous, and since we ain't gonna use it...
* * _beginthreadex() is teh win. :)


18:15 2004-04-25
Things to do before public release:
* At least one full controller (maybe not rumble yet, but at least C-stick and analog L/R). DONE!
* Find a good exe-compressor; we don't want people looking at our strings. DONE: UPX.
* Create a Compability List. DONE!
* Create a website to host the List and otha stuff on. :) DONE!
* * Contact www.emulation64.com for hosting.
* The thread stuff. DONE, I think.
* General config dialog. DONE!
* There may be some logging inconstencies when running multiple DOLs in the same session. Checks it out. DONE, seems cool.
* File drag&drop on teh main window. DONE!
* Send RCs to people for betatesting, fix bugs and issues.
* * /dev/null BBA emulation, remove WinPCap requirement. DONE!


23:10 2004-05-04
Add the following lines to readme.txt once BBA uses SOCK_RAW.
BBA Emulation:
As far as I know, no one's ever emulated a network adapter before, and it needs some explaining.
* First of all, if you don't have an Ethernet card, WhineCube will probably fail rather ungracefully.
* All outgoing packet types other than ARP Request and IPv4 are dropped.
* When an ARP Request is sent by the emulated software, it's captured by WhineCube and an ARP Reply is generated internally.
* All incoming packets types other than IPv4 are dropped.
* IPv4 packets are sent and recieved without modification, except for a special case.
* Some software (most right now, actually) have hardcoded IP addresses. To avoid conflicts, WhineCube can translate outgoing destination and incoming source addresses when they match a user-configurable pair.
* There is also an option to change the outgoing source address to either a user-configurable address or the address used by the network adapter used for the emulation. In that case, packets not addressed to that address are dropped.
18:07 2004-05-15
Forget it.

16:21 2004-05-06
[15:59:05] <tmbinc> re
[16:01:58] <groepaz> morning :)
[16:02:26] <groepaz> checked what the bit for rendering to texture was by any chance? :)
[16:20:28] <tmbinc> just setup 0x49, 0x4a, 0x4d, 0x4b and write 0x5200000
[16:20:37] <tmbinc> 0x52000003 | (format<<4)
[16:26:04] <groepaz> ah ok *notes down* :)

08:15 2004-05-19
  # cat /proc/cpuinfo
  processor       : 0
  cpu             : 745/755
  revision        : 50.20 (pvr 0008 3214)
  bogomips        : 968.70
  vendor          : IBM
  machine         : Nintendo GameCube

04:07 2004-05-20
czn-mp6.dol uses paired single instructions. If these are to be implemented, all existing floating-point instructions may have to be rewritten to retain compability.
17:55 2004-05-23
Or not...

19:12 2004-05-21
Can we assume that GQR writes are rare? I think so, since there are eight of them and they contain configuration data for other instructions.

15:06 2004-05-22
Floats as arguments are passed on the stack, but they're returned in floating-point register ST(0). Thus functions that may be called by recompiled code must return floats as DWORDS. How doubles work is still unknown.



20:13 2004-05-26
GP Draw Quad data format:	//Probably valid for the other draw functions too.
First comes a U16 numVertices, which should probably be a multiple of 4.

Then there's the vertex data, whose format depends on CP registers 0x50, 0x60 and 0x70. (the VAT table)

//There's also bools to indicate the presence of position/normal and texture matrices, but they aren't emulated yet.

Position coords, normal vectors, colors and texture coords. In that order.

  int pos_enc = getbitsw(s_cp_reg[0x50], 21, 22);
  int pos_size = getbitsw(s_cp_reg[0x70], 28, 30);
  bool pos_3d = getbit(s_cp_reg[0x70], 31);
  int pos_shift = getbitsw(s_cp_reg[0x70], 23, 27);

  int norm_enc = getbitsw(s_cp_reg[0x50], 19, 20);
  int norm_size = getbitsw(s_cp_reg[0x70], 19, 21);
  bool norm_nine = getbit(s_cp_reg[0x70], 22);

  int col0_enc = getbitsw(s_cp_reg[0x50], 17, 18);
  int col0_size = getbitsw(s_cp_reg[0x70], 15, 17);
  bool col0_alpha = getbit(s_cp_reg[0x70], 18);

  int col1_enc = getbitsw(s_cp_reg[0x50], 15, 16);
  int col1_size = getbitsw(s_cp_reg[0x70], 11, 13);
  bool col1_alpha = getbit(s_cp_reg[0x70], 14);

  int tex0_enc = getbitsw(s_cp_reg[0x60], 30, 31);
  int tex0_size = getbitsw(s_cp_reg[0x70], 7, 9);
  bool tex0_2d = getbit(s_cp_reg[0x70], 10);
  int tex0_shift = getbitsw(s_cp_reg[0x70], 2, 6);

//Texture coords 1-7 here.

Each piece of the vertex can be formatted individually in three access formats, specified by *_enc in the above table: immediate(01b), 8-bit indexed(10b) and 16-bit indexed(11b). Also, every piece except the position may be omitted, in which case the encoding is 00b.

These are the index base/stride registers:
#define ARRAY_POS_BASE s_cp_reg[0xA0]
#define ARRAY_POS_STRIDE s_cp_reg[0xB0]
#define ARRAY_NORM_BASE s_cp_reg[0xA1]
#define ARRAY_NORM_STRIDE s_cp_reg[0xB1]
#define ARRAY_COL0_BASE s_cp_reg[0xA2]
#define ARRAY_COL0_STRIDE s_cp_reg[0xB2]
#define ARRAY_COL1_BASE s_cp_reg[0xA3]
#define ARRAY_COL1_STRIDE s_cp_reg[0xB3]
#define ARRAY_TEX0_BASE s_cp_reg[0xA4]
#define ARRAY_TEX0_STRIDE s_cp_reg[0xB4]

The base registers contain physical main memory addresses. The stride need not be equal to the size of the vertex data, but if it isn't, things may get confusing. :}

Now for the actual data format. The *_size variables are 3 bits wide and identify the actual value format.
For position and texture coords: 0=U8, 1=S8, 2=U16, 3=S16, 4=float, 5-7 are reserved.
For normals: like pos/tex, except that U8 and U16 formats are not allowed.
For colors: 0 = 16-bit 565, 1 = 24-bit 888, 2 = 32-bit 888x, 3 = 16-bit 4444, 4= 24-bit 6666, 5 = 32-bit 8888.

The bools specify the following:
* The colors are either RGB or RGBA. The three first value formats are valid for three-component colors and the last three are valid for four-component colors. A valid format must be used.
* Position coords are either 2d or 3d.
* Texture coords are either 1d or 2d, though I can't imagine how anyone could use 1d texture coordinates. :}
* Normals seem to be either in 3d or 9d, but they're majorly weird and WhineCube doesn't support them anyway. :p

Position and texture coordinates in any of the integer formats are shifted left by an amount specified in the *_shift variables. I don't know exactly how this shift works, but I've implemented it as a division by (1 << *_shift) after the conversion to float.

Example queue in C struct format, with VAT:

This should draw a background with shifting colors.
struct {
  U8 command = 0x80;	//Draw Quad
  U16 numVertices = 4;	//go figure :}
  struct MY_VERTEX {
    float x, y;
    U32 color;
  } vertices[4] = { { 0, 0, 0xFF000000 }, { 640, 0, 0x00FF0000 },
		    { 0, 480, 0x0000FF00 },  { 640, 480, 0xFF00FF00 } };
} queue;

pos_enc = 1;		//immediate
pos_size = 4;		//float
pos_3d = false;		//2d
pos_shift = 0;		//ignored

col0_enc = 1;		//immediate
col0_size = 2;		//RGB 888x
col0_alpha = false;	//no alpha channel

tex0_enc = 0;		//no texture


Another example, a textured triangle model:

struct {
  U8 command = 0x90;		//Draw Triangles
  U16 numVertices = 3 * 1000;	//lots of triangles :}
  struct INDEXED_VERTEX {
    u16 pos_index;
    u8 tex0_index;
  } vertices[1000];
} queue;

struct MY_VERTEX {
  float x, y, z;
} *pointerToPosCoords = 0x00100000;

struct MY_VERTEX {
  float u, v;
} *pointerToTex0Coords = 0x00200000;

ARRAY_POS_BASE = 0x00100000
ARRAY_POS_STRIDE sizeof(float) * 3;
ARRAY_TEX0_BASE = 0x00200000
ARRAY_TEX0_STRIDE sizeof(float) * 2;

pos_enc = 3;		//16-bit indexed
pos_size = 4;		//float
pos_3d = true;		//3d
pos_shift = 0;		//ignored

col0_enc = 0;		//no color

tex0_enc = 2;		//8-bit indexed
tex0_size = 4;		//float
tex0_2d = true;		//2d
tex0_shift = 0;		//ignored

There, we're done.

18:50 2004-06-12
More GX stuff not in YAGCD:
Little endian.

BP MODE0 (0x80):
bits 21-19	Anisotropic filtering (level? mode?)
bit 5		Min filtering mode 0=point, 1=linear
bit 4		Mag filtering mode
bits 3-2	Wrap_s(t?) (0=GL_CLAMP, 1=GL_CLAMP_TO_EDGE, 2=GL_REPEAT, 3=unknown)
bits 1-0	Wrap_t(s?)

16:11 2004-06-16
XF 0x1020 projection parameters fit into a matrix like this:
A, 0, 0, 0,
0, C, 0, 0,
0, 0, D?E?, 0,
B, D, F, 1, 

21:48 2004-08-15
For BP register 0xF3 (TEV_ALPHAFUNC):
enum { GX_NEVER, GX_LESS, GX_EQUAL, GX_LEQUAL, GX_GREATER, GX_NEQUAL, GX_GEQUAL, GX_ALWAYS } GXCompare;

15:26 2004-09-02
BP register 0x66 is Texture Cache Invalidate. Fields are unknown, but they should contain tmem offset+size.



02:03 2004-05-27
Instructions that change parts of registers need to be aware that source and destination register may be the same, and take special action if needed. It's what caused the snowlords bug and the same bug was just found in ps_merge10. I'ma look through all functions now.
02:38 2004-05-27
Done.
16:43 2004-07-23
There were more bugs in the ps_ functions. Being fixed... ps_madds0, ps_muls0, ps_sum1.
17:02 2004-07-23
Done.

15:29 2004-05-28
czn-mp6 overwrites the instruction at 8001A038 by writing to C001A038. No ICBI, and /amode doesn't detect it since the recompiler works with logical addresses instead of physical. Time to change that.

15:40 2004-05-28
I'm thinking of starting a version history, though it may be superflous since we have todo and done.
00:33 2004-05-29
A release version history would be good. It's one that we can show to the world, which the others aren't.
18:01 2005-04-20
The text file must have a maximum line length of 80 characters.
18:03 2005-04-20
OK, make it 90.

15:24 2004-05-25
GP: Write a detailed description of the Draw commands. The only current information is, I think, in the patents, and they're very hard to read.
23:53 2004-05-26
Done, as far as they're implemented in WhineCube. Add info as more is implemented.

23:58 2004-05-31
DSP notes on task management:
Communication with the DSP is done mostly by mail and interrupts. There are also a few configuration registers in the hardware memory.

The DSP operates on tasks. These tasks are supplied by a higher-level being and contain instructions and data for the DSP. Tasks can be Added, Canceled and Asserted. When a task is Added, it is also Booted. The Boot process sends a bunch of mails to the DSP, which presumably contains all the information the DSP needs to start executing the task.

The DSP interrupt handler can call exec_task, which sends lots of mail and presumably resumes an interrupted task. It can also call remove_task, but Boot and Exec are the only functions besides the handler which sends mail.

Only the handler and Boot reads mail from the DSP.

The AX and Card libraries add tasks. They may have deep magic knowledge. ;)


14:37 2004-06-13
OK, this is how the RTC's gonna work. The RTC is a 32-bit unsigned integer counting seconds since Januari 1st 2000 12:00 AM. The value stored at 0x20000000 in EXI device 0:1 is biased by a value stored in SRAM at offset 0x0C. In WhineCube, this bias will be set to the build time. The main value will be calculated every time it's accessed.

22:03 2004-06-14
GP: When the GP has been activated, none of the old vsync ops will send LM_VSYNC anymore.

21:18 2004-06-18
on Sleep: Statistical analysis shows that Sleep(1) usually takes between 0 and 2 ms. If WCSleep() is called when less than 2 ms remains until the next vsync, time will be lost and the framerate will suffer. Therefore, we will make sure that at least 2 ms remains before we call WCSleep().

23:05 2004-06-23
[22:17:16] <ector> utom locked cache då
[22:17:26] <ector> den behövs till FMV i många spel
[22:17:31] <ector> men knappt nåt annat
[22:17:47] <Masken}> locked cache... den har jag inte rört
[22:19:35] <ector> var busenkel att HLE:a så man såg att det funkade, och LLE visade sig inte vara mycket svårare.. mappa den till 0xE0000000, och sen vid skrivning till ett par såna där SPR-register plocka ut adressbittarna och göra en memcpy typ (DMA från minne till locked cache och tvärtom)

21:51 2004-07-03
for(syp=0; syp<125; syp++){
	for(sxp=0; sxp<180; sxp++){
		x = (sxp)*co[f]+(syp)*si[f];
		y = (sxp)*si[f]-(syp)*co[f];
		//if(bird0_Bitmap[(int)syp][(int)sxp] != 0x69D469EA){
		fbuf[320*(y-63)+(x-90)] = bird0_Bitmap[(int)syp][(int)sxp];
		//}
		++z;
	}
}

13:23 2004-07-15
Of timers and activity (TB and DEC):
*On bootup default values are written. Write-times are not yet relevant.
*When the old values are overwritten, the time of the write is saved together with the value.
*When a register is read, the value stored in it is not updated. Instead, a value computed from the write-time and the written value is returned.
*When _run completes, computed values are written to the registers. Write-times are then irrelevant.
*When _run starts, the write-times are set to the current time.

23:07 2004-07-15
[22:50:30] <or9> i know :( thats shit happened because of DEC or incorrect OS time or unexpected VI interrupts
[22:50:51] <or9> Dolwin is fucking unstable
[22:50:57] <hotquik> heh
[22:50:59] <_Chrono_> bah...
[22:51:11] <Knuckles> :\
[22:51:14] <or9> those 3 things are making me crazy >:[
[22:51:20] <Knuckles> get help.....
[22:51:24] <hotquik> so, based on some experiments desk did....
[22:51:44] <DesktopMa> one tick is 25 nanoseconds
[22:51:49] <hotquik> clock updates around 1 time each 15.44 opcodes
[22:51:56] <DesktopMa> so (ticks*25)/1000000000=seconds
[22:52:40] <Knuckles> is it normal that after 20 second, the year goe sfrom 2000 to 2001 ?

01:22 2004-07-17
[01:13:47] <AziBRB> or9, I found something interesting about the DSP mailbox registers.  It appears data is only sent across when the Mailbox low register is written to.  So you can write to high all you want, but until you write low, it will not set the high bit as being sent.
[01:14:06] <AziBRB> I am reviewing my notes right now since I had to stop due to moving.
[01:15:01] <or9> azi, Dolwin has DSP emulation
[01:15:37] <or9> now we are only need to add AX audio list decode routine to produce sounds
[01:15:48] <or9> (AXPB structure)
[01:16:19] <or9> i have frozen work on sound emulation, when i got DSP working fine
[01:16:19] <AziBRB> Sure... it HLEs the DSP.  But that is not what I was commenting on.
[01:16:36] <or9> well, i know how DSP work in general :)
[01:16:58] <or9> i know that mailbox access asserting DSP interrupt as example
[01:17:25] <or9> and setting of HALT bit in AIDCR register asserting DSP halt exception
[01:17:53] <or9> that mailboxes are mapped in upper DSP memory (same as "ARAM accelerator" and "ADPCM decoder")
[01:18:26] <or9> but that information is useless without knowledge of DSP instruction set
[01:18:42] <AziBRB> yup... do you know the address of ADPCM decoder?  That might be handy.
[01:18:49] <AziBRB> or9: What do you think I am working on?
[01:18:56] <or9> nope
[01:19:18] <or9> i know, that DSP has "extra-hardware" mounted on its address space
[01:19:22] <DesktopMa> AziBRB: Do you have a general idea on how powerful the dsp is?
[01:19:22] <AziBRB> Any little bit of information helps find a pattern, or whatnot...
[01:19:59] <or9> Desk, DSP can do divx decoding real-time
[01:20:02] <AziBRB> DesktopMa: No... I will know very little until I can get DSP registers dumped out to the mailboxes
[01:20:28] <AziBRB> Then I can see its power
[01:20:31] <DesktopMa> or9: I'm pretty sure the ppc is helping on that
[01:20:32] <or9> im wondering why Nintendo didnt made MPEG4 implementation in such way :/
[01:20:51] <or9> (DSP can do decoding in parallel)
[01:21:45] <or9> author of MusyX said in interview, that they tested DSP in-game, playing 64-adpcm coded dolby surround channels, and it wasnt peak rate :)
[01:22:13] <or9> he said it can do more over 100 channels
[01:22:24] <or9> without slowdown
[01:22:38] <DesktopMa> having the dsp mix all sound would be a nice feature for ogclib

09:51 2004-07-20
GP and possibly others: When searching for new things to implement, mask in unhandled bits and see if they change from the (emulated) default.

21:44 2004-08-24
GP textures: Unaligned sizes are allowed, though there are a couple of addressing and filtering exceptions.

20:05 2004-08-25
GP Z values: They are different from Direct3D Z values. This is reflected in all parts of WhineCube which handles Z values, including(bnlt) Projection Matrix, Z compare and EFB Clear.

02:16 2004-08-28
GP Texture format C10 can possibly be optimized by using palettes when the texture in question is using a TLUT with 256 or less entries.
00:12 2004-08-29
DirectX only supports a single active palette. Thus all index-textures must be converted to an appropriate format, RGB565 or RGBA8, depending on TLUT format.

21:12 2004-09-02
GX Tex cache walkthrough of current implementation:
* A texture is loaded, address 1. Its address is added to the hash map. The cache lines are marked invalid and he address is written to them.
* A new texture is loaded, address 2. It's added to the hash map and writes over the cache lines.
* A texture is loaded, address 1. We cannot safely assume that it is still the old texture, as the cache lines indicate a different texture. On a real GC the texture would be reloaded. This would cost us too much in performance, so an exception will be generated. However, if the width, height, mipmap depth or other settings have changed, the texture could be reloaded with optimal performance. For now, we hope that the texture cache will be invalidated before a texture is loaded from address 1.
* A region is invalidated. For every cache line, if the line contains a valid address, the texture with that address is removed from the hash map and Released. The line is set to invalid.
* A texture is loaded, address 1. As its address is not in the hash map, it is loaded just like the one from address 2.
14:54 2004-09-03
Dolphin programs seem to have the habit of invalidating the entire texture cache every frame, somethetimes more than once per frame. We obviously can't keep reconverting all them textures, but we must also maintain cache coherency. Currently I have no reliable solution to this problem.
23:53 2004-09-07
Texture caching has been disabled.

23:52 2004-09-07
All references to the source code(my functions, variables, and so on) should be hidden from the users. I'm thinking primarily of degub logging, where all such references should be conditional on hidden switches, such as /verbose or /map.

20:02 2004-09-15
There's muzak in testdemo4. I just heard it for the first time. :)

14:57 2004-10-26
I just had an idea for netplay (not BBA emu): Send only controller data, and run the emulations independent of each other. Some sort of simple timing/syncing data could also be sent.

21:00 2004-11-09
Since we are unwilling to overwrite illegal opcodes (because they may be data) there may be trouble if the opcode at the end of a block is ever referenced. Remember in case of inexplicable error.

20:15 2004-11-19
Never try to read or write opcodes with data-type memory accesses, since they may be translated differently in Advanced mode.

22:24 2004-11-19
In Advanced Mode, memory blocks which cross virtual page boundaries may be problematic.
03:53 2005-01-12
Memory blocks read/written by the emulated hardware?

03:52 2005-01-12
I'm thinking the BAM problem has to do with interrupts and timing, or, less probably, stwcx.
21:33 2005-01-13
Or maybe... when interrupts are raised while a lower level interrupts are blocked (DI or PI -> EI), then the original interrupt is cleared, then the low-level interrupts are enabled, the original interrupt will still execute... I think. I also think that this should not happen, that instead high-level interrupt status should be read from the hardware memory registers when the lower-level interrupts are enabled.
  This will require some thought, and possibly a remake of the interrupt system.
18:47 2005-01-25
The problem was solved by resetting MSR_EE at gcm boot time. I think the DVD interrupts from the apploader blocked all others, so that no progress could be made. I will add notification to the /lint system to that such situations will be made clearer.

01:44 2005-02-04
Thought on accepting data for the website's Compability List once it starts listing commercial games:
A report that a game works will be accepted regardless of rip quality. A report that a game fails, however, will only be accepted if the game is a proper scene release, or it can be proved that it's an proper rip. In the latter case, notes concerning the state of the rip will be posted. (Unmodified, garbage cleared for better compression, files rearranged for lower gcm file size, and/or other techniques.)

11:49 2005-02-08
Use inline functions instead of macros whenever possible. Among the instances where macros are neccesary are when:
*macro-specific functions, like identifier concatenation, are used.
*the operation is simple and can be used on many data types. Bitwise operations are an example of this.
13:59 2005-02-26
Really avoid declaring temporary variables in macros. They may conflict with already declared variables in the function they're used in, but the compiler won't catch it. See if the compiler can be made to catch it.

12:21 2005-02-08
The AISCNT operation seems to be independent from any actual DVD streaming. Gonna check out dolphin to confirm.
14:12 2005-02-08
Confirmed.
09:14 2005-04-03
Dolphin may have gotten things wrong. Also, AISCNT speed may not be 48kHz after all. Try to check on a real Cube.

21:43 2005-03-08
Eric Nadeau <eric@Surreal-Productions.net><ShizZie on Efnet> has offered to to 2d/3d graphics and website work for WhineCube.

09:12 2005-04-03
Public releases aren't yet speed-focused. PUBLIC_RELEASE should only be used for development and privacy. Go through the code to make sure.
19:16 2005-04-03
Done.

17:07 2005-04-14
#defines that aren't visible from where they're used should be placed in a header file.

23:30 2005-04-18
OPENFILENAME filter strings should be in the singular form for Save As dialogs, and in plural for Open dialogs.

16:54 2005-04-29
PostMessage(WM_CLOSE) must not be used directly. Use CApp::PostCloseMessage() instead.

13:00 2004-11-28
PR plan:
One day or two before a beta is ready, post screenshots or something to let the world know we're still alive. That should get us more testers. :}

15:45 2005-05-13
Texture matrices are kinda weird. This is what I know so far:
*They are stored in xf memory, from 0x78 to oxF0. There are 11 of them, so ten would fit in 0xF0-0x78. Size: 0x78 / 10 = 12 => 3x4 floats per matrix. For 2x4 matrices, only the first 8 floats are used. The remaining four may be stored but are not read by the texgen.
*Texgen mode is set in XF 0x1040(+7).
*Matrix indices are set in BOTH XF 0x1018(+1) and CP 0x30/0x40. I think they must be identical.
*Matrix index numbers seem to be proportional to XF addresses. 0 is 0, 30 is 0x78 and 60 is 0xF0, so address = index * 4.

15:55 2005-06-03
I assume that the address pointed to by FIFO END may be written to, but I'm not positive that it's the case. Dolphin or gcube may help.
16:04 2005-06-03
They don't care much, 'cause they only write in 32-byte bursts. Since FIFO END is 32-byte aligned...?
16:08 2005-06-03
It isn't. It's base+size-4. base and size are aligned.
00:44 2005-06-05
We now use a scheme without a 32-byte gather buffer, writing stuff directly into the FIFO. This will work unless some stupid program decides to write directly to the FIFO without flushing first.

20:43 2005-06-18
Single volatile reads in functions not called by a function using the volatile variable is not harmful, as the variable would have had to be read from memory even if it wasn't volatile. I think.

20:33 2005-06-22
On the use of "invalid" and "unemulated" in error messages:
When used before features with a Uppercase first letter, the word must also have an uppercase first letter. When used last in the error message, they shall have only lowercase letters.
The placement of "invalid" is irrelevant.
The placement of "unemulated" depends on wether all of the feature is unemulated or only part of it. It is placed last only if all of the feature is unemulated. It is placed first otherwise.
The identifier "GP" is placed before all the rest of the error message and is ignored by the above rules.

23:59 2005-09-26
All non-thiscall which may be called by recompiled code must specify calling convention explicitly, as to not cause extra confusion.
23:40 2007-01-05
Or problems when changing default calling convention.

00:36 2006-01-26
Structs are not passed on the stack, even if they're word size. We'll have to pass a pure word as argument, then rebuild the struct inside the functions. Should be optimized equally well.

18:35 2006-01-26
Display List Recompiler works! But it doesn't speed up the IPl noticably... :(
18:37 2006-01-26
Actually, it's at least 100% faster than with /nodlr... seems like the entire emulator has slowed down... again.

23:40 2007-01-05
This is an attempt to document BBA Recieve Buffer behaviour.
	BBA memory is 0x1000 (4K) bytes, addressed flat. The buffer takes 0x100 to the end of BBA memory, which makes 0xF00 (4K - 256) bytes.
	It's treated like a cyclic buffer; it has a read pointer and a write pointer. When the BBA writes to it, it starts at the write pointer, wrapping around at address 0x1000 until it hits the read pointer. Both pointers can be read and written by BBA and CPU alike. They are 16-bit words? Looks shifted right 8 bits. In any case, Write pointer is at 0x16 and Read at 0x18.
	Packets are prepended by a 4-byte Descriptor. The Desciptor contains the length of the packet (including itself) and the high byte of the address where the next packet will start.
	Because the low byte of the next address seems to be missing, all writes are aligned to 0x100 (256) bytes.
	ReadFile, used for reading packets from the TAP driver, doesn't handle circular buffers, so a second buffer is used for WhineCube's first-stage read.
	We can't write to the buffer when it's full. Since it's considered empty when ReadP == WriteP, its maximum fullness is ReadP == WriteP + 0x100. When a recieved packet can't fit in the buffer, ReadFile should not be called again until ReadP has been updated by the CPU so that the waiting Descriptor/Packet can be written into the circular buffer.

12:47 2007-05-01
The random high-speed BBA recv bug is probably due to the fact that I transmit a packet before the BBA's START TRANSMIT bit has been set. Thus the transmit finish interrupt gets sent before the send has even started. Most of the time, this is not a problem, because it takes long enough before the interrupt is handled that the send bit has time to be set. Obviously, "most of the time" is not good enough.
A fix is in progress.
13:02 2007-05-01
Fix implemented, but it didn't help.
17:39 2007-05-01
Next possible cause found: for some reason startRecv isn't called after the reception of the last packet. Thus, no more packets are recieved. Simple.

22:32 2007-09-09
DSP, ADDPAXZ: Seems like that when the magic bit is set, prod is not added with axS.h, but with acD.hm. Result is still stored in acD.hm.
22:39 2007-09-09
Have split opcode where magic bit is set into ADDPZ.
22:46 2007-09-09
No go! It's not when the magic bit is set, but when it's equal to the other parameter bit. That's why there can be only one.

17:04 2008-02-24
use mod.sh like this:
find . -name '*.cpp' -exec mod.sh {} \;
