Now that I've got the SMS message machinery more or less in place, it's time to turn to the contact list. My current concept is for the SMS thread or the contact details (to allow editing of the contact) to be displayed along side this, since the device is basically locked to landscape for a variety of reasons.
My current thinking is just to display a list of contacts on the left, with scrolling as I've done for the SMS threads. We probably do want searching using the index for contacts, so that they can be filtered and found easily.
There also needs to be "new contact" and dial-pad buttons, as well as "call" and "message" buttons on the contact.
But let's step back a moment, and think about the different displays that we want, so that we can architect this properly:
1. Contact list
2. Contact details (including to create a new contact)
3. Dialpad / active call display
4. SMS message list (which also handles call history as pseudo messages)
I'm thinking that each thing can only be displayed on a dedicated half of the screen. So SMS message thread stays on the right-hand side.
The active call display should be on the left. And perhaps that's the only thing that should go on the left.
This means we'd implement the contact list on the right, and have a way to navigate back from the SMS message thread to the contact list. That's not a big problem.
It does mean that we should probably display a banner with the contact name and CALL button next to it at the top of the SMS display.
Let's start with the dialer. I need a nice way to make the dial pad keys. Most likely, those need to be FCM glyphs, so that the digits can be big enough, as the Unicode fonts we have in our proportional text engine are limited to 16px tall. They could be NCM to save some bytes, as I'm not aiming for anything too over the top visually.
I could even use sprites, but we don't have 12 sprites, so I'd have to multiplex or use tall sprites, that would then be tricky to change colour when a given digit is pressed. So FCM/NCM glyphs it will have to be.
Because of the 640x480 video mode, we will probably want each digit to be 8 chars wide and 4 high to look square-ish, with the part with the digit on it taking up a central 4x2 area. So that means we need 4x2 x 64 bytes x 2 (remember we are in interlaced mode) symbols = 1,024 bytes per digit. So 1KB per digit, and we need 12KB overall. We then just need to stash it somewhere above bank 0. I'll have a think about that.
So that just leaves us with needing to make the tool to generate the glyphs, so that we can load them and draw them in place. Probably easiest is to adapt the shared resource font rasteriser, since it's basically the same task, but with a different output layout.
Much of the 12KB will be full of zeroes, though, so it will be worth trying to only keep the non-empty pixel blocks.
I might start by just writing one out, and making sure I have the format right. That way it will be small enough for me to fit the data into the existing test program. Once I have it all right, I can put it on the SD card somewhere, and load it in to an upper bank, without making the memory footprint of the binary bigger -- 12KB would be way too much for that.
Okay, so I have modified the dialpad generator tools, tools/make-dialpad.c, so that if any glyphs (actually interlaced glyph pairs) are all zeroes, then they don't get included in the file. This reduces the whole thing down to 8KB.
We still need somewhere to put it. Banks 4 and 5 are FCM cache, so it can't go there. Bank 0 is the program. Work buffer is 88KB from mid-way through bank 1 to near the end of Bank 2. The rest of Bank 2 is consumed with the C64 KERNAL ROM. Screen RAM is in Bank 1 at $12000, and goes to near $18000.
That all leaves Bank 3, where the C65-mode ROM is, which we can re-use. It also leaves the 8KB at $10000-$11FFF in Bank 1, that CBDOS normally uses. But we aren't using CBDOS, so we can overwrite that. So it looks like a good place to stash it.
Before we can use that, we need our helper program utilities to load files from the SD Card that I had made for the GRAZE web-browser-like program for the MEGA65. So with those, I should be able to have the file stored natively on the SD card in the /PHONE directory, and then load it at address $10000. This also gets us the utility for passing control of one program to another, for when the code inevitably ends up too big to fit in 64KB -- although with LLVM, I'm already fitting in more than I expected.
Okay, I have it partly working, loading the glyphs for the digits and displaying them. Without the SMS display to the right, it looks fine, but when that's there, something upsets some part of it -- possibly via some weird interaction with the interlace mode:
But the digits are being rendered correctly, so that means my tooling for preparing those is all right, which is nice to know :)
I'll take a look at the RRB glitching and figure out the cause tomorrow.
What I have already figured out, though, is that the GOTOX's are the cause of the glitching. But the big question is how?
The issue only shows up if the GOTOX points to a position > 255.
The horizontal jiggle of the SMS display only happens when the high-res text mode is enabled. I'm trying to simplify the address calculation logic for that, even though I can't really see how it could cause this effect.
The GOTOX thing is also a big fat mystery. Maybe this bitstream was generated with poor timing closure or something?
CHARY16 addr calc fix didn't help. But havine 2 GOTOX's instead of one _does_ cause weird things to happen. So I'm assuming it must be a problem latching the 2nd screen RAM byte, since the problem only shows up with a GOTOX > 255.
Fascinatingly it's not whether it's <256 or not, but rather it seems that it's the lower bits of the position that matters. 255 is okay, as is 38x8-1 = 303 is okay, but 256 or 304 are bad. After a bit more mucking about, it turns out the most of the problem is related to whether it's odd or even. Odd is fine, even is bad.
But there are still some other artifacts to resolve:
These gaps and shifted lines seem to be aligned to where the SMS text display to the right are placed. In particular, following the first pixel row of a character row. In that situation we have the badline doing a big fat fetch, so there are fewer RRB cycles available. My best guess is that I just have to reduce the number of render columns.Yup, reducing our render count from 160 to 157 solves the problem:
Right, so now we can add the missing elements. I'd like a time and phone signal display on the top row. Like this:
I'll rearrange things so that it goes flush to the top-right, and the scroll bar for the SMS display doesn't reach the top. But I'm pretty happy with this. We have signal indication, battery level indication. Those were a bit of a bastard to get working, because the unicode codepoints for blocks aren't in the emoji fonts I'm using, so these are actually custom VIC-II mono chars.
But it's all progressing and starting to look like a plausible phone display!
So let's fix the formatting at the top right, and start plumbing more of this together.
I've also refactored the status bar code so that it's now really easy to adjust the widths and positions of the elements using a bunch of #define statements in status.h:
// Space allocations for status bar
#define ST_PX_TIME 64
#define ST_GL_TIME 16
#define ST_PX_NETNAME_START (ST_PX_TIME)
#define ST_GL_NETNAME_START (ST_GL_TIME)
#define ST_PX_NETNAME 128
#define ST_GL_NETNAME 24
#define ST_PX_RESERVED_START (ST_PX_NETNAME_START + ST_PX_NETNAME)
#define ST_GL_RESERVED_START (ST_GL_NETNAME_START + ST_GL_NETNAME)
#define ST_GL_RESERVED 50
#define ST_PX_RESERVED (199+38)
#define ST_PX_INDICATORS_START (ST_PX_RESERVED_START + ST_PX_RESERVED)
#define ST_GL_INDICATORS_START (ST_GL_RESERVED_START + ST_GL_RESERVED)
#define ST_GL_INDICATORS 24
#define ST_PX_INDICATORS 130
#define ST_PX_SIGNAL_START (ST_PX_INDICATORS_START + ST_PX_INDICATORS)
#define ST_GL_SIGNAL_START (ST_GL_INDICATORS_START + ST_GL_INDICATORS)
#define ST_GL_SIGNAL 8
#define ST_PX_SIGNAL 48
#define ST_PX_BATTERY_START (ST_PX_SIGNAL_START + ST_PX_SIGNAL)
#define ST_GL_BATTERY_START (ST_GL_SIGNAL_START + ST_GL_SIGNAL)
#define ST_GL_BATTERY 16
#define ST_PX_BATTERY 64
That's about it for the status bar. So let's make a routine to display a compact form of a contact, so that we can show the contact for whom the SMS is being composed above the SMS thread. We can then re-use that routine for displaying the contact list. With a bit of skullduggery we can also re-use it for editing the contact details. We can indicate which field is active by changing the background colour of the field (or possibly by toggling the reverse field?), and allow the TAB key as well as touch inputs to rotate between them.
This approach also has the advantage that adding a contact requires just allocating the contact record, and then displaying the SMS thread for it. Simple is good :)
Okay, so let's work on displaying contacts. We'll start by showing the currently selected contact above the SMS message list on the right half. All we really need is labels for first name, last name and telephone number. We can just use a Number and Name label to do all that we need. To keep life simple, we can limit each field to a single line.
I have it now displaying that, but there's a glitch with printing the 3rd field box:
The weird thing though, is that the code that draws these fields looks like this, and thus their position should be identical:
char contact_draw(uint8_t x, uint8_t y,
uint16_t x_start_px,
uint8_t w_gl, uint16_t w_px,
unsigned int contact_id,
uint8_t active_field,
unsigned char *contact_record)
{
unsigned char *string;
if (w_gl<20) return 1;
if (w_px<96) return 2;
uint8_t fields[3]={FIELD_FIRSTNAME, FIELD_LASTNAME, FIELD_PHONENUMBER};
unsigned char *labels[3]
={(unsigned char*)"First:",(unsigned char *)"Last: ",(unsigned char *)"Phone:"};
for(uint8_t field=0;field<3;field++) {
draw_string_nowrap(x, y+field,
FONT_UI,
0x0f, // light grey for label text
labels[field],
x_start_px,
LABEL_WIDTH_PX,
LABEL_WIDTH_GL,
NULL,
VIEWPORT_PADDED,
NULL,
NULL);
string = find_field(contact_record, RECORD_DATA_SIZE, fields[field],NULL);
draw_string_nowrap(x + LABEL_WIDTH_GL, y+field,
FONT_UI,
active_field==(field+1) ? 0x8f : 0x8b, // reverse medium grey if not selected
(unsigned char *)string,
x_start_px + LABEL_WIDTH_PX,
w_px - LABEL_WIDTH_PX,
w_gl - LABEL_WIDTH_GL,
NULL,
VIEWPORT_PADDED,
NULL,
NULL);
}
return 0;
}
With some poking around, I can confirm that the 3rd field is being written into the correct characters. That is, the problem is the padding of the "Phone:" label is too wide.
It looks like the issue is when the field has spare glyphs after the padding has reached the intended X position. It's _supposed_ to then fill the remaining space with GOTOX tokens that hold it in position. But something is clearly going wrong with that.
The problem turned out to be how I was passing the viewport information to the drawing calls. That's now fixed and it looks much better. I would like to allow padding on the left of a string instead of on the right, so that I can have right-aligned text. This should be fairly easy by copying the screen and colour RAM across and then putting the padding (and GOTOX tokens with correct changed destination position) following that.
The main complication is that lcopy() isn't safe for overlapping addresses, specifically where the destination starts within the source string.
Got that fixed, and now the weird bug with GOTOX tokens pointing to even addresses has shown up again. I figured it was time once and for all to get to the bottom of that, so I pasted all 250KB of viciv.vhdl into ChatGPT and worked with it a bit to find the problem.
Initially it was suggesting various forms of nonsense, but then by luck or skill it found what I think is the actual problem: In CHARY16 mode, we set bit 0 of the character number when fetching the odd raster lines to achieve the interlace. But if that token's a GOTOX, then on the odd raster lines, that bit forms part of the X position... thus the 1px offset between odd and even raster lines.
It sounds promising, anyway. Cooking a bitstream, and we'll know for sure in a moment -- yup, that fixes it:
In the meantime, let's start plumbing in the TAB key to cycle between the various fields, so that we can use the SMS thread display to also allow editing of the contact details.
I've added an active_field variable that we use to know which field is active. For the SMS message draft box, I now have it so that the cursor appears or hides, depending on which field is active.
I now need to do similar for the contact fields, and also allow editing of them. This mostly consists of keeping track of which field we have in buffers.textbox.draft, so that we know which field to redraw when editing it, and where to stash the result whenever it changes.
This requires a bit of a re-work for the whole text input thing. Not fatally so, but still fairly extensive, because it previously assumed that buffers.textbox.draft only ever held the SMS message draft. But now it will be able to have that, or any of the fields from the contact, or the phone number currently being dialed / DTMF codes being input.
Previously I had the main input loop check at the end of the loop what needed to be (re)drawn. But when you change fields, we need to redraw the old field and the new one. So I'll make a routine to redraw any single field, including knowing whether it's the active field or not, so that background colour is set correctly, and the cursor can be hidden or drawn in the field as appropriate. It shouldn't actually be too hard, just a case of grinding through it.
I've done a bunch of stuff on that, and then also gotten around to caching the D81 mount status, so that we won't unnecessarily re-mount disk images that are already mounted, which should speed a bunch of stuff up -- and it does. It's now much faster to scroll through messages.
I've also done much of the work required for editing any of the fields, including in a contact. And parts of it work nicely now, but things are still going wrong and the contact records are getting corrupted. I've possibly also messed up the provisioning stuff, as when I re-provisioned the SD card, the contacts are fine, but the message thread for the contact was empty.
Let's start by figuring out where the SMS messages from provisioning have gone. It looks like the messages never got written. So let's look at the provisioning stuff: Yup, it looks like the messages don't actually get written. The contacts do, but not the messages in the threads.
It looks like contact 1 gets stuff written properly, but not the others. Looks like this is our problem:
INFO: Rebuilding contact index before importing next SMS
src/telephony/index.c:177:disk_reindex(): Returning with error 1
src/telephony/index.c:246:contacts_reindex(): Returning with error 5
The problem is that I disabled disk_reindex() for native MEGA65 running, because the algorithm is obscenely slow right now. But it's okay for on Linux. So I just need to selectively disable it on MEGA65, but not cross-compiled Linux binaries.
Done, and now we have our message threads back.
In the process, I realised that scrolling the message thread discards changes to the active text field, so we need to fix that, too. But that won't be hard. Done.
Now there's just random crashes when I do stuff that I need to track down.
It looks like delete_field() is causing them. Local variables of the calling function get stomped, or is the stack gets stomped?
Nope, just the interaction of an out-by-one error, the odd semantics of lcopy() on the MEGA65 (a length of 0 means a length of 64KB!) and a couple of other subtle logic bugs. With those fixed, I can now tab through the fields, and the contact fields are getting saved.
There is a problem now with saving and retrieval of the SMS draft, though. This is a bit weird, because it used to be fine. I'm sure it will be some subtle thing again. Tabbing through keeps the SMS draft. The issue is that unless you tab away from it, it doesn't get saved. Actually, that applies to all fields. It's probably okay like that, but it is a change from the earlier semantics where it got saved with every key-press, which ensured you couldn't lose a message draft if the machine crashed, rebooted or was otherwise suddenly stopped.
The more I think about it, the more I think that the old semantics were safer. I just have to see how much it slows things down, as it means removing the cursor, and then putting it back -- in the same place as before, not just at the end of the field. I have code for doing this for when delete is pressed, but not for other edits:
uint16_t cursor_stash = buffers.textbox.draft_cursor_position;
// Remove cursor
textbox_remove_cursor();
// Save changes
af_store(active_field,contact_id);
// Reinsert cursor
textbox_insert_cursor(cursor_stash);
// Redraw
af_redraw(0xff,active_field);
I also have it disabled for the SMS draft field, possibly because I was worried that it would be too slow for long text messages. There's also a weird thing where the first key press when editing the SMS draft field gets munched. Or something weird is happening with it. So I need to get to the bottom of that. I'm suspecting that the length of the field is not properly initialised or something.
I've added some instrumentation, and it looks like it is actually being initialised correctly. So with "abcd" in the message draft, we start with this:
DEBUG: draft
0000: 61 62 63 64 01 00 00 00 00 00 00 00 00 00 00 00 abcd............
draft_len=0x0005, draft_cursor_position=0x0004
Then pressing 'e', the result is:
DEBUG: draft
0000: 61 62 63 64 65 01 00 00 00 00 00 00 00 00 00 00 abcde...........
draft_len=0x0006, draft_cursor_position=0x0005
... which is how it should be. But the 'e' doesn't get displayed. If I then tab through the fields one full loop back to the SMS draft field and press 'f', it is as if the 'e' was never pressed.
But if I do it all over again, then the 'f' is still retained. So what's different between the two events? We know that draft_len and draft_cursor_position and the draft text itself are correctly set and updated. So what goes wrong?
It looks like the edit action itself works. So why does the field re-draw not work?
Hmm... Adding instrumentation seems to suppress the problem. Is it a compiler bug? It's feeling like it: Adding and removing instrumentation changes whether the problem occurs or not. That's really annoying, because making a unit test to elicit this problem isn't going to be simple.
Except it might not be a compiler bug: I can see a situation where the failure to save the field changes after each key press means that it gets discarded by the time the display is redrawn. It still shouldn't happen, but I can see the mechanism. So fixing the save-on-every-change bug should fix this one, too. It's worth a try.
So that has everything almost perfect -- except for the contact fields when selected get redrawn slightly too wide, which is visible after de-selecting them, as the highlight extra bit remains to the right, like I'm pointing at here:
But apart from that, it's all working pretty nicely now:
So let's try to find the cause of that pixel poop. Time to add more instrumentation, this time in the padded string drawing routine, draw_string_nowrap() and it's children.
The pixel pooh is not because the field when highlight is wider. Rather, it looks like the padding of non-highlighted string doesn't use up all of the remaining glyphs, and because of the width of padding glyphs that were in the highlighted version (which had a cursor) are different, that last glyph has a different width to make the padding work. This is also why the pixel pooh is at most 8px wide.
So why is the non-highlighted version not overwriting that last glyph? The only difference in rendering is the lack of cursor -- otherwise it's only the colour. It looks like the padding routine gets called with the correct arguments. So now to find out why it borks.
Well, there we have it: when highlighted, it actually does write one extra glyph. Most fascinating.
[draw_string_nowrap] ENTER xg0=37 yg0=03 f=03 col=8F x_px0=00000197 x_px_vp=000000F7 xg_vp=37 padP=01 utf8=0xBB4F end=0x0000 pxUsed*=0x0000 gUsed*=0x0000
[pad_string_viewport] ENTER xg0=3B yg0=03 col=0F x_px_vp_w=000000E1 xg_vp=37 abs_epx=028E
PAD: glyph=3B , trim=00
...
PAD: glyph=48 , trim=00
PAD: glyph=49 , trim=0F
Backtrace (most recent call first):
[02] 0x55EE draw_string_nowrap+0x01DB, SP=0xD000
[01] 0x7765 af_retrieve+0x000F, SP=0xD000
[00] 0x0C44 main+0x002D, SP=0xD000
[draw_string_nowrap] ENTER xg0=37 yg0=03 f=03 col=8B x_px0=00000197 x_px_vp=000000F7 xg_vp=37 padP=01 utf8=0xBB4F end=0x0000 pxUsed*=0x0000 gUsed*=0x0000
[pad_string_viewport] ENTER xg0=3A yg0=03 col=0B x_px_vp_w=000000E4 xg_vp=37 abs_epx=028E
PAD: glyph=3A , trim=00
...
PAD: glyph=47 , trim=00
PAD: glyph=48 , trim=0C
This is quite odd, because of how the loop is constructed. It should always terminate after the same number of glyphs -- unless we haven't reserved enough glyphs for the field, in which case funny business can occur. But that doesn't seem to be what's happening here.
Found the problem: We only check for equality with x_glyphs_viewport, not if we are greater than. And the values being passed in is the width of the field, rather than the right-hand glyph of the field. Thus it uses a variable number of glyphs, and we get this effect.
Right-o, so that's the last known visual glitch dealt with. On to switching between the SMS thread display and the contact list display. I'm not going to worry about searching or sorting of the contact list right now, just displaying and browsing them. The rest is icing that can wait.
Let's make F3 toggle between contact list and SMS thread display.
We already have a routine that can display the three fields of a contact, so we can re-use that. The main thing we need to do is to refactor things out so that we can support those two different display modes.
A couple of hours of fishing about in the gizzards and hooking everything up, we've now got a nice step forward: Contact list scrolling and selection works :)
In filming that I did hit a bug with the SMS message drafting field. The problem is during deletion it sometimes thinks the message box should be higher up, and possibly consists of multiple lines. There's also a possibly related annoying thing where it's defaulting to * as the message draft, when it should be empty.
Let's look at that * bug: It looks like the * is present in the D81 as 0x2a 0x06 in the start of the draft records. I'm guessing that this is the record number marker we pre-populate at the start of each sector on a record-oriented D81 in records.c.
We can fix it one of two ways: Make it skip over the first two bytes, so that the marker remains intact, or not pre-populate that record with the marker. I've done the first, by sneakily allocating 2 bytes just before the textbox.draft[] array, and reading the record into there, so that it spills over in exactly the right way into the textbox.draft[] array. Net cost: 2 bytes of program size :)
So now lets figure out why editing the SMS draft sometimes causes it to think it's three lines tall instead of just one. It doesn't just happen with delete. It can also happen when typing.
The problem is that calc_break_points() is leaving the number of lines = 3. I think it's junk hanging around in the buffer and a lack of null termination -- but I'm not entirely sure.
My problem now, though, is that I have _finally_ run out of RAM. I'm 61 bytes short of being able to call dump_bytes() to see what's in the draft buffer when this happens. Grr!
Okay, refactored a bit of code to save some space, so that I can get the output now.
It looks like the last rendered SMS message is still hanging around. Or rather, that the af_retrieve() routine is not being called after redrawing the SMS thread display, I think.
Yup -- that was it. I've added an af_dirty flag when retrieving a field so that we know if we need to call calc_line_breaks(), but only need to do it once, so that it doesn't slow things down.
So now all the major GUI bugs have been dealt with. All that's left in this part of things is to implement contact creation, which we'll do in a really simple way: Do the BAM allocation, and then write an empty record to that contact.
... except that results in "/<" in each of the contact fields, because the blank record doesn't have them set, and so the find_field() calls fail, resulting in garbage being returned. Actually, I think it returns a null pointer, which then reads locations $0000 and $0001 before hitting a zero byte at $0002.
Anyway, the solution is probably to build a proper blank contact. I do have a function for that, anyway. Yup, that fixed that. Then a couple of other minor list handling bugs, and a comfort improvement of putting the cursor in the "first name" box when creating a new contact, instead of defaulting onto the SMS draft editing box, and it's looking pretty good. Certainly fit for initial purpose.
So the question now is whether I have enough code space left in this binary to implement the remaining dialer stuff...
Specifically we need a caller/callee bar (which can show a contact or number dialed or be blank), and call / hang-up buttons and call status indicactor, as well as a text field that shows the digits dialed for DTMF injection in the call.
This means we need icons for the dial and hang-up. I'm a bit concerned about where I'm going to find RAM to stash them, so I might tackle those first. It might be possible to use the same tool I made to make the dialpad keys to also make a phone button to represent call, and something to represent hang up.
That increases the size of our dialer glyphs from 6KB to 10KB. We currently stash that at $10000, but we only have 8KB reserved there. So I'll need to move the screen on from $12000 to $12800 at least. I don't remember what else I have stashed away in bank 1. I think work buffers for indexing. Screen is 30 rows x $200 bytes = ~$4000 = 16KB, so I think we can just safely bump the screen address.
Meanwhile, I hit the compiled program size limit again. To work around that for the time being, I've added features.h where I #define various things we can live without for now. Initially, this is just SMS thread indexing, because that's the only thing that requires all of the indexing code. By disabling that, I've won back enough space to keep things compiling for now. I might also have to look at using a cruncher and different memory map at some point, to eek a bit more space, e.g., allowing the program to fully occupy $0200 - $CFFF, and then allowing some data to also be at $E000-$EFFF, and maybe even a bit further up.
But that's all digression for now... let's get those remaining dialer elements in place!
First up, let's draw the call, mute and hang-up buttons:
I still totally love the speak-no-evil monkey as the mute button.
I'm wondering if I shouldn't put the call control buttons down the side of the dial pad, instead of below, as the aspect ratio feels a bit out, and it doesn't leave much space at the top for the contact name of the call plus DTMF digit history from in the call.
Yeah, I think it looks better:
So let's think about call state indication:
1. "Use dialpad or hold-contact to call"
2. "<telephone number + contact name being dialed + Calling>
3 "<telephone number + contact name being dialed + In Call (with timer?) + DTMF box>
4. "<telephone number + contact name being dialed + Incoming Call>
5 "<telephone number + contact name being dialed + Call Ended> (replaces 1 if a call has been made "recently")
It's far from perfect, but it should work as a functional starting point.
The only problem is while implementing it, I'm hitting weird bugs again, which I think are from skirting close to the maximum program size -- just adding an extra string causes consistent crashes, but without generating a compile or link-time error.
So I'm going to have to find something else that I can selectively disable. SMS sending is a fairly obvious candidate, but the problem there is that the call state handling actually needs to record pseudo-messages to indicate received, missed calls etc.
I could lose the function list for stack back-trace, but that would only gain about 1/2 KB right now. But I might as well take the free bonus I can get from trimming some of the bootstrap symbol names that are really long like /usr/local/bin/../mos-platform/c64/lib/libcrt0.a(init-stack.S.obj):(.init.100). By cutting those at the last /, we can drop them down to something like libcrt0.a(init-stack.S.obj):(.init.100).
So that fixed the problem (for now), so it really does seem to be some self-stomping problem when we get close to using all RAM --- possibly the software stack goes down and treads on something. Anyway, I don't have time to track the problem down right now.
Now I'm tracking down a bunch of weird display glitches, most of which are related to the annoying RRB glitch thing. I really would like to know the cause and be able to fix it, because it's really cramping a bunch of things.
Changes to $D05E (the number of glyphs that should be rendered) cause changes in the display, even when the extra glyphs should never appear on the screen. I'm assuming it's something crazy in the RRB paint state-machine not resetting at the start of the next raster if it's doing some specific phase of activity. Anyway, I've worked around it by reducing the number of rendered columns, but allowing the text renderer to pretend the display is a bit wider, so that we don't get notching on the right-hand side.
Now the last remaining visual glitch is when scrolling down through an SMS thread the draft message field disappears sometimes, messing things up. One part of the problem is the cursor deletion code is trimming when there is no cursor. Fixed that, and also selection of the correct field by default when displaying a contact. Apart from the lack of cursor in the dialpad fields, and that you can't do anything with them, it's now looking good and glitch-free.
Well almost glitch free, typing some letters results in bogus glyphs appearing, instead of the correct ones. I think the glyph cache is incorrectly claiming to have the corresponding codepoint loaded, but it ends up having some other glyph in there.
Lower-case K is doing it reliably for me right now, so let's look and see what's in the cache. And it is claiming to be there in slot 73. We use 256 bytes per glyph, so the data should be at $44900-$449FF.
The problem only occurs if the character hasn't already been included somewhere on the screen. On start it isn't in the cache, but then typing it (with the contact that I'm currently displaying) it does indeed get loaded into slot 73 --- but clearly the data is getting messed up somehow.
And now I can't reproduce it anymore :/
Oh well, I'll track it down when it shows up next.
But let's get the cursor and editing working for the dialer fields. For simplicity, we'll only allow the cursor to be at the end of the dialer field. And the DTMF history in-call won't even have a cursor. It should also only appear when in-call and post-call.
Okay, cursor working, and also highlighting dialpad buttons should work now, too... except that I've run out of RAM again. I managed to find enough debug code that was hanging around to get it working again, and with a bit of fiddling, the dialpad does what we expect :)
And I think I'll stop here to post this, before it ends up even longer, still.












