From 04b7ccfd87d802e6b9a22b86c8d098979164b8ba Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Mon, 15 Aug 2022 23:03:30 -0400 Subject: undo started --- undo.cpp | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 undo.cpp (limited to 'undo.cpp') diff --git a/undo.cpp b/undo.cpp new file mode 100644 index 0000000..7858f8d --- /dev/null +++ b/undo.cpp @@ -0,0 +1,146 @@ +// get ready for some MLG... + +// These get four things pushed together: the address of what's being +// changed, what type the data is, the original data, and the type again. +// The type is encoded twice so we always know how big the data is whether +// we're undoing or redoing. +// We need to encode data that's able to go from A -> B as well as B -> A. Thus +// for the ints I encode the difference instead of just whatever the last value +// was. Strings currently just stores both. +void Action_Change_Commit(memory *Memory, void *OriginalData, void *NewData, action_change_type ActionChange) +{ + void *UndoEntry = AllocateMemory(Memory, sizeof(void *), P_UndoBuffer); + *(ptrsize *)UndoEntry = (ptrsize)OriginalData; + void *Data = AllocateMemory(Memory, sizeof(action_change_type), P_UndoBuffer); + *(action_change_type *)Data = ActionChange; + switch (ActionChange) + { + case action_change_u16: + { + uint16 OriginalValue = *(uint16 *)OriginalData; + uint16 NewValue = *(uint16 *)NewData; + uint16 Difference = NewValue - OriginalValue; + void *Data = AllocateMemory(Memory, sizeof(uint16), P_UndoBuffer); + *(uint16 *)Data = Difference; + *(uint16 *)OriginalData = *(uint16 *)NewData; + } break; + case action_change_i16: + { + int16 OriginalValue = *(int16 *)OriginalData; + int16 NewValue = *(int16 *)NewData; + int16 Difference = NewValue - OriginalValue; + void *Data = AllocateMemory(Memory, sizeof(int16), P_UndoBuffer); + *(int16 *)Data = Difference; + *(int16 *)OriginalData = *(int16 *)NewData; + } break; + case action_change_u32: + { + uint32 OriginalValue = *(uint32 *)OriginalData; + uint32 NewValue = *(uint32 *)NewData; + uint32 Difference = NewValue - OriginalValue; + void *Data = AllocateMemory(Memory, sizeof(uint32), P_UndoBuffer); + *(uint32 *)Data = Difference; + *(uint32 *)OriginalData = *(uint32 *)NewData; + } break; + case action_change_i32: + { + int32 OriginalValue = *(int32 *)OriginalData; + int32 NewValue = *(int32 *)NewData; + int32 Difference = NewValue - OriginalValue; + void *Data = AllocateMemory(Memory, sizeof(int32), P_UndoBuffer); + *(int32 *)Data = Difference; + *(int32 *)OriginalData = *(int32 *)NewData; + } break; + case action_change_r32: + { + real32 OriginalValue = *(real32 *)OriginalData; + real32 NewValue = *(real32 *)NewData; + real32 Difference = NewValue - OriginalValue; + void *Data = AllocateMemory(Memory, sizeof(real32), P_UndoBuffer); + *(real32 *)Data = Difference; + *(real32 *)OriginalData = *(real32 *)NewData; + } break; + case action_change_u64: + { + uint64 OriginalValue = *(uint64 *)OriginalData; + uint64 NewValue = *(uint64 *)NewData; + uint64 Difference = NewValue - OriginalValue; + void *Data = AllocateMemory(Memory, sizeof(uint64), P_UndoBuffer); + *(uint64 *)Data = Difference; + *(uint64 *)OriginalData = *(uint64 *)NewData; + } break; + case action_change_ptr: + { + ptrsize OriginalValue = *(ptrsize *)OriginalData; + ptrsize NewValue = *(ptrsize *)NewData; + ptrsize Difference = NewValue - OriginalValue; + void *Data = AllocateMemory(Memory, sizeof(ptrsize), P_UndoBuffer); + *(ptrsize *)Data = Difference; + *(ptrsize *)OriginalData = *(ptrsize *)NewData; + } break; + case action_change_string: + { + void *Data = AllocateMemory(Memory, STRING_SIZE, P_UndoBuffer); + CopyStrings(Data, OriginalData); + Data = AllocateMemory(Memory, STRING_SIZE, P_UndoBuffer); + CopyStrings(Data, NewData); + CopyStrings(OriginalData, NewData); + } break; + } + Data = AllocateMemory(Memory, sizeof(action_change_type), P_UndoBuffer); + *(action_change_type *)Data = ActionChange; +} + +// TODO(fox): Maybe take the extra lines to separate the incrementing of the +// address from the variable assignment to improve legibility. + +// The pointer is unwinded. +void Action_Undo(memory *Memory) { + memory_table *Table = &Memory->Slot[P_UndoBuffer]; + uint8 *LastPos = (uint8 *)Table->Address + Table->CurrentPosition; + action_change_type *ActionType = (action_change_type *)LastPos - 1; + uint8 *TableAddress; + switch (*ActionType) + { + case action_change_u16: + { + uint16 *Difference = (uint16 *)ActionType - 1; + TableAddress = (uint8 *)Difference - sizeof(ptrsize) - sizeof(action_change_type); + void *Address = (void *)*(ptrsize *)TableAddress; + *(uint16 *)Address -= *Difference; + } break; + case action_change_ptr: + { + ptrsize *Difference = (ptrsize *)ActionType - 1; + TableAddress = (uint8 *)Difference - sizeof(ptrsize) - sizeof(action_change_type); + void *Address = (void *)*(ptrsize *)TableAddress; + *(ptrsize *)Address -= *Difference; + } break; + } + Table->CurrentPosition = (TableAddress - (uint8 *)Table->Address); +} + +// The pointer is rewinded. +void Action_Redo(memory *Memory) { + memory_table *Table = &Memory->Slot[P_UndoBuffer]; + uint8 *LastPos = (uint8 *)Table->Address + Table->CurrentPosition; + void *Address = (void *)*(ptrsize *)LastPos; + action_change_type *ActionType = (action_change_type *)(LastPos + sizeof(void *)); + uint8 *TableAddress; + switch (*ActionType) + { + case action_change_u16: + { + uint16 *Difference = (uint16 *)(ActionType + 1); + TableAddress = (uint8 *)Difference + sizeof(uint16) + sizeof(action_change_type); + *(uint16 *)Address += *Difference; + } break; + case action_change_ptr: + { + ptrsize *Difference = (ptrsize *)(ActionType + 1); + TableAddress = (uint8 *)Difference + sizeof(ptrsize) + sizeof(action_change_type); + *(ptrsize *)Address += *Difference; + } break; + } + Table->CurrentPosition = (TableAddress - (uint8 *)Table->Address); +} -- cgit v1.2.3