I suppose you could do that, but it sounds really painful. At that point, I just recognized that the answer would necessarily be a natural number, so all you have to do is find a number A such that sqrt(A2+((200(A-100))/(A-200))2) is a whole number. That sounds like random guessing, but I already had a good idea of the value of A, so I really only had to deal with thirty values or so, which is easily done in your head.
int main() { long a, b, c; long aa, bb, cc; for (a = 1; a <= 200; ++a) { aa = a*a; for (b = 1; b <= 200 - a - 1; ++b) { bb = b*b; c = 200 - a - b; cc = c*c; if (c > 0 && aa + bb == cc) printf("a=%ld b=%ld c=%ld\n", a,b,c); } } return 0; }
Spoiler For solution:
When I ran the program I got this answer: a=40 b=75 c=85 a=75 b=40 c=85
(one solution and the other trivial solution with A and B reversed)
40^2 + 75^2 = 85^2 40, 75, and 85 all are natural numbers 40 + 75 + 85 = 200
QED.
Time between reading the problem and instructing the computer how to find a solution: less than 5 minutes Time to run the program and obtain a solution: 4 milliseconds Finding a solution in less time than doing it purely by hand: priceless
Great! I'm glad to see TI-89 support added. Does this includes TI-89 Titanium support as well?
Not yet. There shouldn't be too much to change to get it working on the Titanium, as far as the memory layout goes, but I haven't even tried porting to it yet.
I'm happy to announce Beta 4! This beta includes initial TI-89 support, remote terminal support (using two calculators and the "uterm" program), and user logins.
I just released Beta 3, now with vfork()! This means multi-tasking works now.
The current shell can't run any pipelines or background processes, so multi-tasking is only marginally useful at this stage, but it's an important piece of the puzzle for later on.
As for virtual pages, it sounds like a great idea to start. However, it would get pretty inefficient, pretty fast. Imagine you're several GCs into the usage of the filesystem. The virtual pages end up completely different then the normal ones. When looking for file entries, or reading from a stream, crossing page boundaries becomes very slow - you'd have to swap through every physical page until you find the virtual one you need.
You can scan the pages at boot time and keep a table in RAM to map virtual pages to real pages. This can be as simple as an array of bytes, the size being determined by the number of Flash pages (how many pages are there anyway? 32?). To find the real page number for a given virtual page number, just use the virtual page number as an index into the array, and read the byte at that position. That byte is the real page number. When you swap pages (as in, use the floating swap page), you just have to update a couple of bytes in the array.
If you align your array on a 256-byte boundary, the code to translate virtual to real page numbers can be this simple (note: I haven't tested this code):
Ok, I changed it to a tiny hourglass. I already tried to draw an hourglass before I posted, but I didn't like the way it turned out. Speaking of the status icons, I don't really like how the hand icon looks either. I think it looks like a claw. I don't really have a use for the "claw" button anyway. Maybe I could use it to switch to different virtual terminals using claw+F1 through F8.
I noticed that Garbage Dir has ID 0x01 and Directory has ID 0xFE. For deleting a directory or file, is the idea to mark it as deleted by clearing some of the bits in the ID? If so, you won't be able to get an ID of 0x01 by clearing some bits from 0xFE, since bit 0 is already clear in 0xFE. For deleted directory you could use the ID 0x02 instead.
Also, the way the swapping is done is pretty wasteful. It wears down FlashROM at least twice as fast as needed, and takes twice as long too. The way I would do it is to use a floating swap page rather than a fixed swap page. What this means is, instead of copying a page to the swap page and then back to the original page, copy a page to the swap page and then make the old page the new swap page.
To implement this you might have to use virtual page numbers. The first byte of each real page can contain the virtual page number for that page. So, for example, if real page 5 is virtual page 9, then all references to page 9 (say, a file entry with the file contents on page 9) will read from or write to the real page number 5. When you need to swap that page, then you can move the whole virtual page to the swap page easily and make real page 5 the new swap page. This adds a little bit of overhead but gives you much better performance overall.
Additionally, for a little bit of protection against incomplete page erases, you could add a few bytes (a magic value like "KFS") to the beginning/end of a page after it is erased. If your routines read a page that doesn't contain that magic value, then you know that the page wasn't erased properly. Erase the page and write the magic value (and virtual page number) to it.
The rest of the spec looks decent, but it is kind of a shame that only one writable stream can be open at a time. It's cool to see that it supports nested directories and long file names, though.
This is the first time I see a quadruple post here I think, although it's fine due to the large period of time between all. That goes to tell how we need a few more 68K users.
I'm glad this is still progressing well.
Heh, it's actually five. I didn't realize I posted so many in a row when I did it. You're right, we do need more 68k folks around here.
Anyway, I just added a busy indicator to the bottom status line (next to the battery status). I think it's pretty cool watching it flicker as programs run and pause:
What does everyone think about the status icon itself? I don't particularly care for it, but it was the best I could come up with. Can anyone draw a better one? (Should I ask this in the Pixel Art and Drawing board instead?)
Good So my wild guess about a read at offset 0x2E from address 1 actually proved to be correct...
Yup. I think I'll improve my exception handlers one of these days so they'll provide more information about the exception in human-readable formats (only when it happens in kernel mode. I'll want to send a signal and/or kill a process if it happens in user mode)
The bug you've reported on the TIEmu SF tracker looks odd. TIEmu has no business reading data one byte off their valid locations...
I noticed in both working and non-working (crashing) TIB files the long value 0xCCCCCCCC immediately before the SSP and PC, but in the crashing TIB, there is an additional 0xCC byte before that long value. That is probably just the last byte of a length or pointer value. Does TiEmu look for 0xCCCCCCCC as a marker or signature of sorts? If so then it would start at the previous byte for that reason.
if (time_before(p->p_deadline, current->p_deadline)) { Somehow the value 1 is passed in for p, and the p_deadline member is at offset 0x2e in the proc structure, so this is attempting to access a long value at p->p_deadline at address 0x2f.
So the address exception doesn't contain the return address but rather the address that some code attempted to access non-word aligned.
Now I finally bother reading M68000PRM.pdf. Here's the stack frame for address error exceptions (in pretty ASCII art ):
Therefore this address exception and the stack frame make more sense.
I still have to figure out what is calling set_state() with the value 1.
EDIT: I just found it. I called set_run (which calls set_state) without any arguments, so whatever value happened to be on the stack was used as the value for p. FAIL
EDIT 2: Lo and behold, that fixed the problem!! I guess I should use function prototypes more thoroughly, since TIGCC would give an error if I had a prototype for sched_run().
EDIT 3: Actually, calling sched_run() from that place (in tsleep() in process.c) was a bug itself. The process was already scheduled to run at that time so it was trying to schedule a process that was already running. I just had to remove the line completely. Now my scheduler and (due to my recent clock/timer fixes) timers are extremely stable!
Alright, after many hours of searching for the root cause, I still haven't a real clue. But I finally have a real starting place.
Inside the system call (trap #0) handler I set the interrupt level to 1 to block the system clock (level 1) interrupt from running during a system call. This seems to stop the address error from happening. This isn't an actual fix, though, since I still want the system clock to run during system calls (otherwise the system slows down due to missed interrupts). This only points the finger at the system clock interrupt handler, or some bad interaction between it and a system call.
During this time I also uncovered a handful of other minor synchronization issues and bugs, and I greatly simplified the system clock (it was a kind of kludgey mix of the int 1 and int 3 clocks), so this bug hunt wasn't a complete waste of time. None of these changes warrant a new beta, so I'll just keep looking for this pesky bug.